From 7b855c851d7824596557d4444796c2c3aec6356c Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 5 Oct 2024 12:29:31 +0200 Subject: [PATCH 01/52] Added integer based `sin()/cos()` functions, changed all trig functions to wled_math - `sin16_t() / cos16_t()` are faster and more accurate than fastled versions - `sin_approx() / cos_approx()` are float wrappers for `sin16_t() / cos16_t()` and are accurate enough to replace `sinf()/cosf()` - `atan2()` is used only in octopus to calculate center offset, new approximated version saves flash - `tan(), atan(), asin(), acos(), floor(), fmod()` are used only for sunrise/sunset calculation, using wled_math version saves flash - `beatsinx()` replacements are to make use of new `sin16_t()/sin8_t()` functions to reduce flash size - Extensively tested surnise/sunset calculation: deviation is 1min. max - Tested some of the relevant FX and found no visual difference: Julia, 2D Drift, Drift Rose, Ghost rider, Rotozoomer, Palette, Arc 1D expansion - total flash savings: 7.4k --- usermods/Analog_Clock/Analog_Clock.h | 4 +- wled00/FX.cpp | 258 +++++++++++++-------------- wled00/fcn_declare.h | 53 +++--- wled00/util.cpp | 41 ++++- wled00/wled_math.cpp | 89 ++++++++- 5 files changed, 288 insertions(+), 157 deletions(-) diff --git a/usermods/Analog_Clock/Analog_Clock.h b/usermods/Analog_Clock/Analog_Clock.h index 596f0acb3..9d82f7670 100644 --- a/usermods/Analog_Clock/Analog_Clock.h +++ b/usermods/Analog_Clock/Analog_Clock.h @@ -102,9 +102,9 @@ private: void secondsEffectSineFade(int16_t secondLed, Toki::Time const& time) { uint32_t ms = time.ms % 1000; - uint8_t b0 = (cos8(ms * 64 / 1000) - 128) * 2; + uint8_t b0 = (cos8_t(ms * 64 / 1000) - 128) * 2; setPixelColor(secondLed, gamma32(scale32(secondColor, b0))); - uint8_t b1 = (sin8(ms * 64 / 1000) - 128) * 2; + uint8_t b1 = (sin8_t(ms * 64 / 1000) - 128) * 2; setPixelColor(inc(secondLed, 1, secondsSegment), gamma32(scale32(secondColor, b1))); } diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f3e82275c..338dd2df9 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -39,7 +39,7 @@ // effect utility functions uint8_t sin_gap(uint16_t in) { if (in & 0x100) return 0; - return sin8(in + 192); // correct phase shift of sine so that it starts and stops at 0 + return sin8_t(in + 192); // correct phase shift of sine so that it starts and stops at 0 } uint16_t triwave16(uint16_t in) { @@ -349,7 +349,7 @@ uint16_t mode_breath(void) { counter = (counter >> 2) + (counter >> 4); //0-16384 + 0-2048 if (counter < 16384) { if (counter > 8192) counter = 8192 - (counter - 8192); - var = sin16(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 + var = sin16_t(counter) / 103; //close to parabolic in range 0-8192, max val. 23170 } unsigned lum = 30 + var; @@ -531,7 +531,7 @@ static uint16_t running_base(bool saw, bool dual=false) { } a = 255 - a; } - uint8_t s = dual ? sin_gap(a) : sin8(a); + uint8_t s = dual ? sin_gap(a) : sin8_t(a); uint32_t ca = color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s); if (dual) { unsigned b = (SEGLEN-1-i)*x_scale - counter; @@ -1893,16 +1893,16 @@ uint16_t mode_pride_2015(void) { unsigned sPseudotime = SEGENV.step; unsigned sHue16 = SEGENV.aux0; - uint8_t sat8 = beatsin88( 87, 220, 250); - uint8_t brightdepth = beatsin88( 341, 96, 224); - unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); - unsigned msmultiplier = beatsin88(147, 23, 60); + uint8_t sat8 = beatsin88_t( 87, 220, 250); + uint8_t brightdepth = beatsin88_t( 341, 96, 224); + unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); + unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16;//gHue * 256; - unsigned hueinc16 = beatsin88(113, 1, 3000); + unsigned hueinc16 = beatsin88_t(113, 1, 3000); sPseudotime += duration * msmultiplier; - sHue16 += duration * beatsin88( 400, 5,9); + sHue16 += duration * beatsin88_t( 400, 5,9); unsigned brightnesstheta16 = sPseudotime; for (unsigned i = 0 ; i < SEGLEN; i++) { @@ -1910,7 +1910,7 @@ uint16_t mode_pride_2015(void) { uint8_t hue8 = hue16 >> 8; brightnesstheta16 += brightnessthetainc16; - unsigned b16 = sin16( brightnesstheta16 ) + 32768; + unsigned b16 = sin16_t( brightnesstheta16 ) + 32768; unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; @@ -1935,7 +1935,7 @@ uint16_t mode_juggle(void) { CRGB fastled_col; byte dothue = 0; for (int i = 0; i < 8; i++) { - int index = 0 + beatsin88((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); + int index = 0 + beatsin88_t((16 + SEGMENT.speed)*(i + 7), 0, SEGLEN -1); fastled_col = CRGB(SEGMENT.getPixelColor(index)); fastled_col |= (SEGMENT.palette==0)?CHSV(dothue, 220, 255):ColorFromPalette(SEGPALETTE, dothue, 255); SEGMENT.setPixelColor(index, fastled_col); @@ -1956,8 +1956,8 @@ uint16_t mode_palette() { constexpr mathType maxAngle = 0x8000; constexpr mathType staticRotationScale = 256; constexpr mathType animatedRotationScale = 1; - constexpr int16_t (*sinFunction)(uint16_t) = &sin16; - constexpr int16_t (*cosFunction)(uint16_t) = &cos16; + constexpr int16_t (*sinFunction)(uint16_t) = &sin16_t; + constexpr int16_t (*cosFunction)(uint16_t) = &cos16_t; #else using mathType = float; using wideMathType = float; @@ -2141,15 +2141,15 @@ uint16_t mode_colorwaves() { unsigned sPseudotime = SEGENV.step; unsigned sHue16 = SEGENV.aux0; - unsigned brightdepth = beatsin88(341, 96, 224); - unsigned brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); - unsigned msmultiplier = beatsin88(147, 23, 60); + unsigned brightdepth = beatsin88_t(341, 96, 224); + unsigned brightnessthetainc16 = beatsin88_t( 203, (25 * 256), (40 * 256)); + unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16;//gHue * 256; - unsigned hueinc16 = beatsin88(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues + unsigned hueinc16 = beatsin88_t(113, 60, 300)*SEGMENT.intensity*10/255; // Use the Intensity Slider for the hues sPseudotime += duration * msmultiplier; - sHue16 += duration * beatsin88(400, 5, 9); + sHue16 += duration * beatsin88_t(400, 5, 9); unsigned brightnesstheta16 = sPseudotime; for (int i = 0 ; i < SEGLEN; i++) { @@ -2163,7 +2163,7 @@ uint16_t mode_colorwaves() { } brightnesstheta16 += brightnessthetainc16; - unsigned b16 = sin16(brightnesstheta16) + 32768; + unsigned b16 = sin16_t(brightnesstheta16) + 32768; unsigned bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; @@ -2182,7 +2182,7 @@ static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!"; // colored stripes pulsing at a defined Beats-Per-Minute (BPM) uint16_t mode_bpm() { uint32_t stp = (strip.now / 20) & 0xFF; - uint8_t beat = beatsin8(SEGMENT.speed, 64, 255); + uint8_t beat = beatsin8_t(SEGMENT.speed, 64, 255); for (int i = 0; i < SEGLEN; i++) { SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(stp + (i * 2), false, PALETTE_SOLID_WRAP, 0, beat - stp + (i * 10))); } @@ -2198,7 +2198,7 @@ uint16_t mode_fillnoise8() { unsigned index = inoise8(i * SEGLEN, SEGENV.step + i * SEGLEN); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); } - SEGENV.step += beatsin8(SEGMENT.speed, 1, 6); //10,1,4 + SEGENV.step += beatsin8_t(SEGMENT.speed, 1, 6); //10,1,4 return FRAMETIME; } @@ -2210,13 +2210,13 @@ uint16_t mode_noise16_1() { SEGENV.step += (1 + SEGMENT.speed/16); for (int i = 0; i < SEGLEN; i++) { - unsigned shift_x = beatsin8(11); // the x position of the noise field swings @ 17 bpm + unsigned shift_x = beatsin8_t(11); // the x position of the noise field swings @ 17 bpm unsigned shift_y = SEGENV.step/42; // the y position becomes slowly incremented unsigned real_x = (i + shift_x) * scale; // the x position of the noise field swings @ 17 bpm unsigned real_y = (i + shift_y) * scale; // the y position becomes slowly incremented uint32_t real_z = SEGENV.step; // the z position becomes quickly incremented unsigned noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map LED color based on noise data + unsigned index = sin8_t(noise * 3); // map LED color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); } @@ -2234,7 +2234,7 @@ uint16_t mode_noise16_2() { unsigned shift_x = SEGENV.step >> 6; // x as a function of time uint32_t real_x = (i + shift_x) * scale; // calculate the coordinates within the noise field unsigned noise = inoise16(real_x, 0, 4223) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map led color based on noise data + unsigned index = sin8_t(noise * 3); // map led color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); } @@ -2255,7 +2255,7 @@ uint16_t mode_noise16_3() { uint32_t real_y = (i + shift_y) * scale; // based on the precalculated positions uint32_t real_z = SEGENV.step*8; unsigned noise = inoise16(real_x, real_y, real_z) >> 8; // get the noise data and scale it down - unsigned index = sin8(noise * 3); // map led color based on noise data + unsigned index = sin8_t(noise * 3); // map led color based on noise data SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, noise)); } @@ -2335,13 +2335,13 @@ static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade spe //Calm effect, like a lake at night uint16_t mode_lake() { unsigned sp = SEGMENT.speed/10; - int wave1 = beatsin8(sp +2, -64,64); - int wave2 = beatsin8(sp +1, -64,64); - int wave3 = beatsin8(sp +2, 0,80); + int wave1 = beatsin8_t(sp +2, -64,64); + int wave2 = beatsin8_t(sp +1, -64,64); + int wave3 = beatsin8_t(sp +2, 0,80); for (int i = 0; i < SEGLEN; i++) { - int index = cos8((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; + int index = cos8_t((i*15)+ wave1)/2 + cubicwave8((i*23)+ wave2)/2; uint8_t lum = (index > wave3) ? index - wave3 : 0; SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, false, 0, lum)); } @@ -2514,7 +2514,7 @@ static uint16_t ripple_base() { propI /= 2; unsigned cx = rippleorigin >> 8; unsigned cy = rippleorigin & 0xFF; - unsigned mag = scale8(sin8((propF>>2)), amp); + unsigned mag = scale8(sin8_t((propF>>2)), amp); if (propI > 0) SEGMENT.drawCircle(cx, cy, propI, color_blend(SEGMENT.getPixelColorXY(cx + propI, cy), col, mag), true); } else #endif @@ -2581,7 +2581,7 @@ static CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) unsigned ticks = ms / SEGENV.aux0; unsigned fastcycle8 = ticks; unsigned slowcycle16 = (ticks >> 8) + salt; - slowcycle16 += sin8(slowcycle16); + slowcycle16 += sin8_t(slowcycle16); slowcycle16 = (slowcycle16 * 2053) + 1384; unsigned slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8); @@ -3152,7 +3152,7 @@ static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of b static uint16_t sinelon_base(bool dual, bool rainbow=false) { if (SEGLEN == 1) return mode_static(); SEGMENT.fade_out(SEGMENT.intensity); - unsigned pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); + unsigned pos = beatsin16_t(SEGMENT.speed/10,0,SEGLEN-1); if (SEGENV.call == 0) SEGENV.aux0 = pos; uint32_t color1 = SEGMENT.color_from_palette(pos, true, false, 0); uint32_t color2 = SEGCOLOR(2); @@ -3868,13 +3868,13 @@ uint16_t mode_plasma(void) { if (SEGENV.call == 0) { SEGENV.aux0 = random8(0,2); // add a bit of randomness } - unsigned thisPhase = beatsin8(6+SEGENV.aux0,-64,64); - unsigned thatPhase = beatsin8(7+SEGENV.aux0,-64,64); + unsigned thisPhase = beatsin8_t(6+SEGENV.aux0,-64,64); + unsigned thatPhase = beatsin8_t(7+SEGENV.aux0,-64,64); for (unsigned i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set color & brightness based on a wave as follows: unsigned colorIndex = cubicwave8((i*(2+ 3*(SEGMENT.speed >> 5))+thisPhase) & 0xFF)/2 // factor=23 // Create a wave and add a phase change and add another wave with its own phase change. - + cos8((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish. - unsigned thisBright = qsub8(colorIndex, beatsin8(7,0, (128 - (SEGMENT.intensity>>1)))); + + cos8_t((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2; // factor=15 // Hey, you can even change the frequencies if you wish. + unsigned thisBright = qsub8(colorIndex, beatsin8_t(7,0, (128 - (SEGMENT.intensity>>1)))); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0, thisBright)); } @@ -4001,10 +4001,10 @@ static CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, u unsigned wavescale_half = (wavescale >> 1) + 20; waveangle += ((120 + SEGMENT.intensity) * i); //original 250 * i - unsigned s16 = sin16(waveangle) + 32768; + unsigned s16 = sin16_t(waveangle) + 32768; unsigned cs = scale16(s16, wavescale_half) + wavescale_half; ci += (cs * i); - unsigned sindex16 = sin16(ci) + 32768; + unsigned sindex16 = sin16_t(ci) + 32768; unsigned sindex8 = scale16(sindex16, 240); return ColorFromPalette(p, sindex8, bri, LINEARBLEND); } @@ -4036,34 +4036,34 @@ uint16_t mode_pacifica() uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7); strip.now = deltat; - unsigned speedfactor1 = beatsin16(3, 179, 269); - unsigned speedfactor2 = beatsin16(4, 179, 269); + unsigned speedfactor1 = beatsin16_t(3, 179, 269); + unsigned speedfactor2 = beatsin16_t(4, 179, 269); uint32_t deltams1 = (deltams * speedfactor1) / 256; uint32_t deltams2 = (deltams * speedfactor2) / 256; uint32_t deltams21 = (deltams1 + deltams2) / 2; - sCIStart1 += (deltams1 * beatsin88(1011,10,13)); - sCIStart2 -= (deltams21 * beatsin88(777,8,11)); - sCIStart3 -= (deltams1 * beatsin88(501,5,7)); - sCIStart4 -= (deltams2 * beatsin88(257,4,6)); + sCIStart1 += (deltams1 * beatsin88_t(1011,10,13)); + sCIStart2 -= (deltams21 * beatsin88_t(777,8,11)); + sCIStart3 -= (deltams1 * beatsin88_t(501,5,7)); + sCIStart4 -= (deltams2 * beatsin88_t(257,4,6)); SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2; SEGENV.step = sCIStart4; SEGENV.step = (SEGENV.step << 16) + sCIStart3; // Clear out the LED array to a dim background blue-green //SEGMENT.fill(132618); - unsigned basethreshold = beatsin8( 9, 55, 65); + unsigned basethreshold = beatsin8_t( 9, 55, 65); unsigned wave = beat8( 7 ); for (int i = 0; i < SEGLEN; i++) { CRGB c = CRGB(2, 6, 10); // Render each of four layers, with different scales and speeds, that vary over time - c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16(3, 11 * 256, 14 * 256), beatsin8(10, 70, 130), 0-beat16(301)); - c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16(4, 6 * 256, 9 * 256), beatsin8(17, 40, 80), beat16(401)); - c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3, 6 * 256 , beatsin8(9, 10,38) , 0-beat16(503)); - c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4, 5 * 256 , beatsin8(8, 10,28) , beat16(601)); + c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16_t(3, 11 * 256, 14 * 256), beatsin8_t(10, 70, 130), 0-beat16(301)); + c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16_t(4, 6 * 256, 9 * 256), beatsin8_t(17, 40, 80), beat16(401)); + c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3, 6 * 256 , beatsin8_t(9, 10,38) , 0-beat16(503)); + c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4, 5 * 256 , beatsin8_t(8, 10,28) , beat16(601)); // Add extra 'white' to areas where the four layers of light have lined up brightly - unsigned threshold = scale8( sin8( wave), 20) + basethreshold; + unsigned threshold = scale8( sin8_t( wave), 20) + basethreshold; wave += 7; unsigned l = c.getAverageLight(); if (l > threshold) { @@ -4187,7 +4187,7 @@ uint16_t mode_twinkleup(void) { // A very short twinkle routine for (int i = 0; i < SEGLEN; i++) { unsigned ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work. - unsigned pixBri = sin8(ranstart + 16 * strip.now/(256-SEGMENT.speed)); + unsigned pixBri = sin8_t(ranstart + 16 * strip.now/(256-SEGMENT.speed)); if (random8() > SEGMENT.intensity) pixBri = 0; SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri)); } @@ -4230,7 +4230,7 @@ uint16_t mode_noisepal(void) { // Slow noise SEGMENT.setPixelColor(i, color.red, color.green, color.blue); } - SEGENV.aux0 += beatsin8(10,1,4); // Moving along the distance. Vary it a bit with a sine wave. + SEGENV.aux0 += beatsin8_t(10,1,4); // Moving along the distance. Vary it a bit with a sine wave. return FRAMETIME; } @@ -4312,7 +4312,7 @@ uint16_t mode_chunchun(void) for (unsigned i = 0; i < numBirds; i++) { counter -= span; - unsigned megumin = sin16(counter) + 0x8000; + unsigned megumin = sin16_t(counter) + 0x8000; unsigned bird = uint32_t(megumin * SEGLEN) >> 16; uint32_t c = SEGMENT.color_from_palette((i * 255)/ numBirds, false, false, 0); // no palette wrapping bird = constrain(bird, 0U, SEGLEN-1U); @@ -4481,7 +4481,7 @@ uint16_t mode_washing_machine(void) { SEGENV.step += (speed * 2048) / (512 - SEGMENT.speed); for (int i = 0; i < SEGLEN; i++) { - uint8_t col = sin8(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); + uint8_t col = sin8_t(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(col, false, PALETTE_SOLID_WRAP, 3)); } @@ -4837,8 +4837,8 @@ static const char _data_FX_MODE_PERLINMOVE[] PROGMEM = "Perlin Move@!,# of pixel uint16_t mode_wavesins(void) { for (int i = 0; i < SEGLEN; i++) { - uint8_t bri = sin8(strip.now/4 + i * SEGMENT.intensity); - uint8_t index = beatsin8(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider + uint8_t bri = sin8_t(strip.now/4 + i * SEGMENT.intensity); + uint8_t index = beatsin8_t(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider //SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, index, bri, LINEARBLEND)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, bri)); } @@ -4860,9 +4860,9 @@ uint16_t mode_FlowStripe(void) { for (int i = 0; i < SEGLEN; i++) { int c = (abs(i - hl) / hl) * 127; - c = sin8(c); - c = sin8(c / 2 + t); - byte b = sin8(c + t/8); + c = sin8_t(c); + c = sin8_t(c / 2 + t); + byte b = sin8_t(c + t/8); SEGMENT.setPixelColor(i, CHSV(b + hue, 255, 255)); } @@ -4889,14 +4889,14 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma unsigned long t = strip.now/128; // timebase // outer stars for (size_t i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8_t(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); + y = beatsin8_t(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(i*32, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); } // inner stars for (size_t i = 0; i < 4; i++) { - x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8_t(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); + y = beatsin8_t(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(255-i*64, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255)); } // central white dot @@ -4930,10 +4930,10 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGENV.aux0++; // hue SEGMENT.fadeToBlackBy(40); for (size_t i = 0; i < numLines; i++) { - byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1)); - byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1)); - byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); - byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); + byte x1 = beatsin8_t(2 + SEGMENT.speed/16, 0, (cols - 1)); + byte x2 = beatsin8_t(1 + SEGMENT.speed/16, 0, (rows - 1)); + byte y1 = beatsin8_t(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); + byte y2 = beatsin8_t(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); byte xsteps = abs8(x1 - y1) + 1; @@ -4972,8 +4972,8 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa SEGMENT.fadeToBlackBy(64); for (int i = 0; i < cols; i++) { - SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); - SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); + SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10), LINEARBLEND)); + SEGMENT.setPixelColorXY(i, beatsin8_t(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8_t(5, 55, 255, 0, i*10+128), LINEARBLEND)); } SEGMENT.blur(SEGMENT.intensity>>3); @@ -5002,8 +5002,8 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma SEGMENT.fadeToBlackBy(135); for (int i = 0; i < rows; i++) { - int x = beatsin8(speeds, 0, cols - 1, 0, i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, i * freq + 128); - int x1 = beatsin8(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); + int x = beatsin8_t(speeds, 0, cols - 1, 0, i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, i * freq + 128); + int x1 = beatsin8_t(speeds, 0, cols - 1, 0, 128 + i * freq) + beatsin8_t(speeds - 7, 0, cols - 1, 0, 128 + 64 + i * freq); unsigned hue = (i * 128 / rows) + ms; // skip every 4th row every now and then (fade it more) if ((i + ms / 8) & 3) { @@ -5104,9 +5104,9 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so SEGMENT.fadeToBlackBy(16); for (size_t i = 8; i > 0; i--) { - SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1), - beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), - ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); + SEGMENT.addPixelColorXY(beatsin8_t(SEGMENT.speed/8 + i, 0, cols - 1), + beatsin8_t(SEGMENT.intensity/8 - i, 0, rows - 1), + ColorFromPalette(SEGPALETTE, beatsin8_t(12, 0, 255), 255, LINEARBLEND)); } SEGMENT.blur(SEGMENT.custom1>>3); @@ -5238,7 +5238,7 @@ uint16_t mode_2DHiphotic() { // By: ldirko https://edit for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8(cos8(x * SEGMENT.speed/16 + a / 3) + sin8(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); + SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(sin8_t(cos8_t(x * SEGMENT.speed/16 + a / 3) + sin8_t(y * SEGMENT.intensity/16 + a / 4) + a), false, PALETTE_SOLID_WRAP, 0)); } } @@ -5378,10 +5378,10 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline //for (int i=0; i < 4*(cols+rows); i ++) { for (int i=0; i < 256; i ++) { - //float xlocn = float(sin8(now/4+i*(SEGMENT.speed>>5))) / 255.0f; - //float ylocn = float(cos8(now/4+i*2)) / 255.0f; - uint_fast8_t xlocn = sin8(phase/2 + (i*SEGMENT.speed)/32); - uint_fast8_t ylocn = cos8(phase/2 + i*2); + //float xlocn = float(sin8_t(now/4+i*(SEGMENT.speed>>5))) / 255.0f; + //float ylocn = float(cos8_t(now/4+i*2)) / 255.0f; + uint_fast8_t xlocn = sin8_t(phase/2 + (i*SEGMENT.speed)/32); + uint_fast8_t ylocn = cos8_t(phase/2 + i*2); xlocn = (cols < 2) ? 1 : (map(2*xlocn, 0,511, 0,2*(cols-1)) +1) /2; // softhack007: "(2* ..... +1) /2" for proper rounding ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2; // "rows > 1" is needed to avoid div/0 in map() SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); @@ -5481,8 +5481,8 @@ uint16_t mode_2Dmetaballs(void) { // Metaballs by Stefan Petrick. Cannot have int y3 = map(inoise8(strip.now * speed, 25355, 22685), 0, 255, 0, rows-1); // and one Lissajou function - int x1 = beatsin8(23 * speed, 0, cols-1); - int y1 = beatsin8(28 * speed, 0, rows-1); + int x1 = beatsin8_t(23 * speed, 0, cols-1); + int y1 = beatsin8_t(28 * speed, 0, rows-1); for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) { @@ -5647,7 +5647,7 @@ uint16_t mode_2DPulser(void) { // By: ldirko https://edi SEGMENT.fadeToBlackBy(8 - (SEGMENT.intensity>>5)); uint32_t a = strip.now / (18 - SEGMENT.speed / 16); int x = (a / 14) % cols; - int y = map((sin8(a * 5) + sin8(a * 4) + sin8(a * 2)), 0, 765, rows-1, 0); + int y = map((sin8_t(a * 5) + sin8_t(a * 4) + sin8_t(a * 2)), 0, 765, rows-1, 0); SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, map(y, 0, rows-1, 0, 255), 255, LINEARBLEND)); SEGMENT.blur(SEGMENT.intensity>>4); @@ -5673,10 +5673,10 @@ uint16_t mode_2DSindots(void) { // By: ldirko http SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3); byte t1 = strip.now / (257 - SEGMENT.speed); // 20; - byte t2 = sin8(t1) / 4 * 2; + byte t2 = sin8_t(t1) / 4 * 2; for (int i = 0; i < 13; i++) { - int x = sin8(t1 + i * SEGMENT.intensity/8)*(cols-1)/255; // max index now 255x15/255=15! - int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! + int x = sin8_t(t1 + i * SEGMENT.intensity/8)*(cols-1)/255; // max index now 255x15/255=15! + int y = sin8_t(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } SEGMENT.blur(SEGMENT.custom2>>3); @@ -5703,12 +5703,12 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g SEGMENT.blur(SEGMENT.custom3>>1); // Use two out-of-sync sine waves - int i = beatsin8(19, kBorderWidth, cols-kBorderWidth); - int j = beatsin8(22, kBorderWidth, cols-kBorderWidth); - int k = beatsin8(17, kBorderWidth, cols-kBorderWidth); - int m = beatsin8(18, kBorderWidth, rows-kBorderWidth); - int n = beatsin8(15, kBorderWidth, rows-kBorderWidth); - int p = beatsin8(20, kBorderWidth, rows-kBorderWidth); + int i = beatsin8_t(19, kBorderWidth, cols-kBorderWidth); + int j = beatsin8_t(22, kBorderWidth, cols-kBorderWidth); + int k = beatsin8_t(17, kBorderWidth, cols-kBorderWidth); + int m = beatsin8_t(18, kBorderWidth, rows-kBorderWidth); + int n = beatsin8_t(15, kBorderWidth, rows-kBorderWidth); + int p = beatsin8_t(20, kBorderWidth, rows-kBorderWidth); SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, strip.now/29, 255, LINEARBLEND)); SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, strip.now/41, 255, LINEARBLEND)); @@ -5784,19 +5784,19 @@ uint16_t mode_2Dtartan(void) { // By: Elliott Kember https://editor.so uint8_t hue, bri; size_t intensity; - int offsetX = beatsin16(3, -360, 360); - int offsetY = beatsin16(2, -360, 360); + int offsetX = beatsin16_t(3, -360, 360); + int offsetY = beatsin16_t(2, -360, 360); int sharpness = SEGMENT.custom3 / 8; // 0-3 for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - hue = x * beatsin16(10, 1, 10) + offsetY; - intensity = bri = sin8(x * SEGMENT.speed/2 + offsetX); + hue = x * beatsin16_t(10, 1, 10) + offsetY; + intensity = bri = sin8_t(x * SEGMENT.speed/2 + offsetX); for (int i=0; i>= 8*sharpness; SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); hue = y * 3 + offsetX; - intensity = bri = sin8(y * SEGMENT.intensity/2 + offsetY); + intensity = bri = sin8_t(y * SEGMENT.intensity/2 + offsetY); for (int i=0; i>= 8*sharpness; SEGMENT.addPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, hue, intensity, LINEARBLEND)); @@ -5831,9 +5831,9 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht SEGMENT.move(SEGENV.aux0, 1); for (size_t i = 0; i < 8; i++) { - int x = beatsin8(12 + i, 2, cols - 3); - int y = beatsin8(15 + i, 2, rows - 3); - CRGB color = ColorFromPalette(SEGPALETTE, beatsin8(12 + i, 0, 255), 255); + int x = beatsin8_t(12 + i, 2, cols - 3); + int y = beatsin8_t(15 + i, 2, rows - 3); + CRGB color = ColorFromPalette(SEGPALETTE, beatsin8_t(12 + i, 0, 255), 255); SEGMENT.addPixelColorXY(x, y, color); if (cols > 24 || rows > 24) { SEGMENT.addPixelColorXY(x+1, y, color); @@ -6229,8 +6229,8 @@ uint16_t mode_2Ddriftrose(void) { SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3)); for (size_t i = 1; i < 37; i++) { float angle = radians(i * 10); - uint32_t x = (CX + (sin_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; - uint32_t y = (CY + (cos_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; + uint32_t x = (CX + (sin_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; + uint32_t y = (CY + (cos_t(angle) * (beatsin8_t(i, 0, L*2)-L))) * 255.f; SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); } SEGMENT.blur(SEGMENT.intensity>>4); @@ -6426,8 +6426,8 @@ uint16_t mode_2DSwirl(void) { SEGMENT.blur(SEGMENT.custom1); - int i = beatsin8( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); - int j = beatsin8( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); + int i = beatsin8_t( 27*SEGMENT.speed/255, borderWidth, cols - borderWidth); + int j = beatsin8_t( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth); int ni = (cols - 1) - i; int nj = (cols - 1) - j; @@ -6639,7 +6639,7 @@ uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline. for (size_t i=0; ithisphase += 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. + plasmoip->thisphase += beatsin8_t(6,-4,4); // You can change direction and speed individually. + plasmoip->thatphase += beatsin8_t(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline. for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows. // updated, similar to "plasma" effect - softhack007 uint8_t thisbright = cubicwave8(((i*(1 + (3*SEGMENT.speed/32)))+plasmoip->thisphase) & 0xFF)/2; - thisbright += cos8(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. + thisbright += cos8_t(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. uint8_t colorIndex=thisbright; if (volumeSmth * SEGMENT.intensity / 64 < thisbright) {thisbright = 0;} @@ -7280,7 +7280,7 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac frTemp -= 132.0f; // This should give us a base musical note of C3 frTemp = fabsf(frTemp * 2.1f); // Fudge factors to compress octave range starting at 0 and going to 255; - unsigned i = map(beatsin8(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); + unsigned i = map(beatsin8_t(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1); i = constrain(i, 0U, SEGLEN-1U); SEGMENT.addPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint8_t)frTemp, false, PALETTE_SOLID_WRAP, 0), volTemp)); @@ -7567,12 +7567,12 @@ uint16_t mode_2Ddistortionwaves() { unsigned a2 = a/2; unsigned a3 = a/3; - unsigned cx = beatsin8(10-speed,0,cols-1)*scale; - unsigned cy = beatsin8(12-speed,0,rows-1)*scale; - unsigned cx1 = beatsin8(13-speed,0,cols-1)*scale; - unsigned cy1 = beatsin8(15-speed,0,rows-1)*scale; - unsigned cx2 = beatsin8(17-speed,0,cols-1)*scale; - unsigned cy2 = beatsin8(14-speed,0,rows-1)*scale; + unsigned cx = beatsin8_t(10-speed,0,cols-1)*scale; + unsigned cy = beatsin8_t(12-speed,0,rows-1)*scale; + unsigned cx1 = beatsin8_t(13-speed,0,cols-1)*scale; + unsigned cy1 = beatsin8_t(15-speed,0,rows-1)*scale; + unsigned cx2 = beatsin8_t(17-speed,0,cols-1)*scale; + unsigned cy2 = beatsin8_t(14-speed,0,rows-1)*scale; unsigned xoffs = 0; for (int x = 0; x < cols; x++) { @@ -7582,17 +7582,17 @@ uint16_t mode_2Ddistortionwaves() { for (int y = 0; y < rows; y++) { yoffs += scale; - byte rdistort = cos8((cos8(((x<<3)+a )&255)+cos8(((y<<3)-a2)&255)+a3 )&255)>>1; - byte gdistort = cos8((cos8(((x<<3)-a2)&255)+cos8(((y<<3)+a3)&255)+a+32 )&255)>>1; - byte bdistort = cos8((cos8(((x<<3)+a3)&255)+cos8(((y<<3)-a) &255)+a2+64)&255)>>1; + byte rdistort = cos8_t((cos8_t(((x<<3)+a )&255)+cos8_t(((y<<3)-a2)&255)+a3 )&255)>>1; + byte gdistort = cos8_t((cos8_t(((x<<3)-a2)&255)+cos8_t(((y<<3)+a3)&255)+a+32 )&255)>>1; + byte bdistort = cos8_t((cos8_t(((x<<3)+a3)&255)+cos8_t(((y<<3)-a) &255)+a2+64)&255)>>1; byte valueR = rdistort+ w* (a- ( ((xoffs - cx) * (xoffs - cx) + (yoffs - cy) * (yoffs - cy))>>7 )); byte valueG = gdistort+ w* (a2-( ((xoffs - cx1) * (xoffs - cx1) + (yoffs - cy1) * (yoffs - cy1))>>7 )); byte valueB = bdistort+ w* (a3-( ((xoffs - cx2) * (xoffs - cx2) + (yoffs - cy2) * (yoffs - cy2))>>7 )); - valueR = gamma8(cos8(valueR)); - valueG = gamma8(cos8(valueG)); - valueB = gamma8(cos8(valueB)); + valueR = gamma8(cos8_t(valueR)); + valueG = gamma8(cos8_t(valueG)); + valueB = gamma8(cos8_t(valueB)); SEGMENT.setPixelColorXY(x, y, RGBW32(valueR, valueG, valueB, 0)); } @@ -7749,7 +7749,7 @@ uint16_t mode_2Doctopus() { const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255; for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - rMap[XY(x, y)].angle = 40.7436f * atan2f((y - C_Y), (x - C_X)); // avoid 128*atan2()/PI + rMap[XY(x, y)].angle = 40.7436f * atan2_t((y - C_Y), (x - C_X)); // avoid 128*atan2()/PI rMap[XY(x, y)].radius = hypotf((x - C_X), (y - C_Y)) * mapp; //thanks Sutaburosu } } @@ -7760,8 +7760,8 @@ uint16_t mode_2Doctopus() { for (int y = 0; y < rows; y++) { byte angle = rMap[XY(x,y)].angle; byte radius = rMap[XY(x,y)].radius; - //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); - unsigned intensity = sin8(sin8((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); + //CRGB c = CHSV(SEGENV.step / 2 - radius, 255, sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step) + radius - SEGENV.step * 2 + angle * (SEGMENT.custom3/3+1))); + unsigned intensity = sin8_t(sin8_t((angle * 4 - radius) / 4 + SEGENV.step/2) + radius - SEGENV.step + angle * (SEGMENT.custom3/4+1)); intensity = map((intensity*intensity) & 0xFFFF, 0, 65535, 0, 255); // add a bit of non-linearity for cleaner display CRGB c = ColorFromPalette(SEGPALETTE, SEGENV.step / 2 - radius, intensity); SEGMENT.setPixelColorXY(x, y, c); @@ -7769,7 +7769,7 @@ uint16_t mode_2Doctopus() { } return FRAMETIME; } -static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs;;!;2;"; +static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offset Y,Legs,fasttan;;!;2;"; //Waving Cell @@ -7786,7 +7786,7 @@ uint16_t mode_2Dwavingcell() { uint8_t aY = SEGMENT.custom2/16 + 1; uint8_t aZ = SEGMENT.custom3 + 1; for (int x = 0; x < cols; x++) for (int y = 0; y T atan_t(T x); - float cos_t(float phi); - float sin_t(float x); - float tan_t(float x); - float acos_t(float x); - float asin_t(float x); - float floor_t(float x); - float fmod_t(float num, float denom); -#else - #include - #define sin_t sinf - #define cos_t cosf - #define tan_t tanf - #define asin_t asinf - #define acos_t acosf - #define atan_t atanf - #define fmod_t fmodf - #define floor_t floorf -#endif +//float cos_t(float phi); // use float math +//float sin_t(float phi); +//float tan_t(float x); +int16_t sin16_t(uint16_t theta); +int16_t cos16_t(uint16_t theta); +uint8_t sin8_t(uint8_t theta); +uint8_t cos8_t(uint8_t theta); +float sin_approx(float theta); // uses integer math (converted to float), accuracy +/-0.0015 (compared to sinf()) +float cos_approx(float theta); +float tan_approx(float x); +float atan2_t(float y, float x); +float acos_t(float x); +float asin_t(float x); +template T atan_t(T x); +float floor_t(float x); +float fmod_t(float num, float denom); +#define sin_t sin_approx +#define cos_t cos_approx +#define tan_t tan_approx +/* +#include // standard math functions. use a lot of flash +#define sin_t sinf +#define cos_t cosf +#define tan_t tanf +#define asin_t asinf +#define acos_t acosf +#define atan_t atanf +#define fmod_t fmodf +#define floor_t floorf +*/ //wled_serial.cpp void handleSerial(); void updateBaudRate(uint32_t rate); diff --git a/wled00/util.cpp b/wled00/util.cpp index 0b78a4646..c43fdeabf 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -372,6 +372,39 @@ uint16_t crc16(const unsigned char* data_p, size_t length) { return crc; } +// fastled beatsin: 1:1 replacements to remove the use of fastled sin16() +// Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) +{ + uint16_t beat = beat88( beats_per_minute_88, timebase); + uint16_t beatsin (sin16_t( beat + phase_offset) + 32768); + uint16_t rangewidth = highest - lowest; + uint16_t scaledbeat = scale16( beatsin, rangewidth); + uint16_t result = lowest + scaledbeat; + return result; +} + +// Generates a 16-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset) +{ + uint16_t beat = beat16( beats_per_minute, timebase); + uint16_t beatsin = (sin16_t( beat + phase_offset) + 32768); + uint16_t rangewidth = highest - lowest; + uint16_t scaledbeat = scale16( beatsin, rangewidth); + uint16_t result = lowest + scaledbeat; + return result; +} + +// Generates an 8-bit sine wave at a given BPM that oscillates within a given range. see fastled for details. +uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest, uint8_t highest, uint32_t timebase, uint8_t phase_offset) +{ + uint8_t beat = beat8( beats_per_minute, timebase); + uint8_t beatsin = sin8_t( beat + phase_offset); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8( beatsin, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} /////////////////////////////////////////////////////////////////////////////// // Begin simulateSound (to enable audio enhanced effects to display something) @@ -431,8 +464,8 @@ um_data_t* simulateSound(uint8_t simulationId) default: case UMS_BeatSin: for (int i = 0; i<16; i++) - fftResult[i] = beatsin8(120 / (i+1), 0, 255); - // fftResult[i] = (beatsin8(120, 0, 255) + (256/16 * i)) % 256; + fftResult[i] = beatsin8_t(120 / (i+1), 0, 255); + // fftResult[i] = (beatsin8_t(120, 0, 255) + (256/16 * i)) % 256; volumeSmth = fftResult[8]; break; case UMS_WeWillRockYou: @@ -469,12 +502,12 @@ um_data_t* simulateSound(uint8_t simulationId) break; case UMS_10_13: for (int i = 0; i<16; i++) - fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); + fftResult[i] = inoise8(beatsin8_t(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3); volumeSmth = fftResult[8]; break; case UMS_14_3: for (int i = 0; i<16; i++) - fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); + fftResult[i] = inoise8(beatsin8_t(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3); volumeSmth = fftResult[8]; break; } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index a4c9fc123..401446a23 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -12,6 +12,12 @@ #define modd(x, y) ((x) - (int)((x) / (y)) * (y)) +// Note: cos_t, sin_t and tan_t are very accurate but may be slow +// the math.h functions use several kB of flash and are to be avoided if possible +// sin16_t / cos16_t are faster and much more accurate than the fastled variants +// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy of +/-0.0015 compared to sinf() +// sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate + float cos_t(float phi) { float x = modd(phi, TWO_PI); @@ -31,8 +37,8 @@ float cos_t(float phi) return res; } -float sin_t(float x) { - float res = cos_t(HALF_PI - x); +float sin_t(float phi) { + float res = cos_t(HALF_PI - phi); #ifdef WLED_DEBUG_MATH Serial.printf("sin: %f,%f,%f,(%f)\n",x,res,sin(x),res-sin(x)); #endif @@ -49,6 +55,85 @@ float tan_t(float x) { return res; } +// 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) +// input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) +// optimized integer implementation by @dedehai +int16_t sin16_t(uint16_t theta) { + int scale = 1; + if (theta > 0x7FFF) { + theta = 0xFFFF - theta; + scale = -1; // second half of the sine function is negative (pi - 2*pi) + } + uint32_t precal = theta * (0x7FFF - theta); + uint64_t numerator = (uint64_t)precal * (4 * 0x7FFF); // 64bit required + int32_t denominator = 1342095361 - precal; // 1342095361 is 5 * 0x7FFF^2 / 4 + int16_t result = numerator / denominator; + return result * scale; +} + +int16_t cos16_t(uint16_t theta) { + return sin16_t(theta + 16384); //cos(x) = sin(x+pi/2) +} + +uint8_t sin8_t(uint8_t theta) { + int32_t sin16 = sin16_t((uint16_t)theta * 257); // 255 * 257 = 0xFFFF + sin16 += 0x7FFF; //shift result to range 0-0xFFFF + return sin16 >> 8; +} + +uint8_t cos8_t(uint8_t theta) { + return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) +} + +float sin_approx(float theta) +{ + theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range + if(theta < 0) theta += M_TWOPI; // 0-2pi range + uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / M_TWOPI)); + int32_t result = sin16_t(scaled_theta); + float sin = float(result) / 0x7FFF; + return sin; +} + +float cos_approx(float theta) +{ + return sin_approx(theta + M_PI_2); +} + +float tan_approx(float x) { + float c = cos_approx(x); + if (c==0.0f) return 0; + float res = sin_approx(x) / c; + return res; +} + +#define ATAN2_CONST_A 0.1963f +#define ATAN2_CONST_B 0.9817f + +// fast atan2() approximation source: public domain +float atan2_t(float y, float x) { + if (x == 0.0f) return (y > 0.0f) ? M_PI_2 : (y < 0.0f) ? -M_PI_2 : 0.0f; + + float abs_y = (y < 0.0f) ? -y : y + 1e-10f; // make sure y is not zero to prevent division by 0 + float z = abs_y / x; + float atan_approx; + + if (z < 1.0f) { + atan_approx = z / (1.0f + ATAN2_CONST_A * z * z); + if (x < 0.0f) { + return (y >= 0.0f) ? atan_approx + PI : atan_approx - PI; + } + } + else { + z = x / abs_y; + atan_approx = M_PI_2 - z / (1.0f + ATAN2_CONST_A * z * z); + if (y < 0.0f) { + return -atan_approx; + } + } + return atan_approx; +} + //https://stackoverflow.com/questions/3380628 // Absolute error <= 6.7e-5 float acos_t(float x) { From f301296f1e1c9ba9ceeb49aead1f89fc3cd94ba6 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 6 Oct 2024 21:27:58 +0200 Subject: [PATCH 02/52] added rounding to sin8_t thx to @softhack007 --- wled00/wled_math.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 401446a23..080cc9425 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -77,8 +77,8 @@ int16_t cos16_t(uint16_t theta) { uint8_t sin8_t(uint8_t theta) { int32_t sin16 = sin16_t((uint16_t)theta * 257); // 255 * 257 = 0xFFFF - sin16 += 0x7FFF; //shift result to range 0-0xFFFF - return sin16 >> 8; + sin16 += 0x7FFF + 128; //shift result to range 0-0xFFFF, +128 for rounding + return min(sin16, int32_t(0xFFFF)) >> 8; // min performs saturation, and prevents overflow } uint8_t cos8_t(uint8_t theta) { From 5e29f2c1b7844492c5ccaf194f524fe810947c3f Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 15 Oct 2024 20:11:33 +0200 Subject: [PATCH 03/52] fixed atan2_t approximation was incorrect, now doing it right. also removed hypotf() from octopus, saving a little flash. --- wled00/FX.cpp | 6 ++++-- wled00/wled_math.cpp | 39 +++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 338dd2df9..5b4513dc7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7749,8 +7749,10 @@ uint16_t mode_2Doctopus() { const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255; for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - rMap[XY(x, y)].angle = 40.7436f * atan2_t((y - C_Y), (x - C_X)); // avoid 128*atan2()/PI - rMap[XY(x, y)].radius = hypotf((x - C_X), (y - C_Y)) * mapp; //thanks Sutaburosu + rMap[XY(x, y)].angle = int(40.7436f * atan2_t((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI + int dx = (x - C_X); + int dy = (y - C_Y); + rMap[XY(x, y)].radius = sqrtf(dx * dx + dy * dy) * mapp; //thanks Sutaburosu } } } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 080cc9425..1825ab198 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -88,8 +88,8 @@ uint8_t cos8_t(uint8_t theta) { float sin_approx(float theta) { theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range - if(theta < 0) theta += M_TWOPI; // 0-2pi range - uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / M_TWOPI)); + if(theta < 0) theta += TWO_PI; // 0-2pi range + uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / TWO_PI)); int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; @@ -110,28 +110,23 @@ float tan_approx(float x) { #define ATAN2_CONST_A 0.1963f #define ATAN2_CONST_B 0.9817f -// fast atan2() approximation source: public domain +// atan2_t approximation, with the idea from https://gist.github.com/volkansalma/2972237?permalink_comment_id=3872525#gistcomment-3872525 float atan2_t(float y, float x) { - if (x == 0.0f) return (y > 0.0f) ? M_PI_2 : (y < 0.0f) ? -M_PI_2 : 0.0f; - - float abs_y = (y < 0.0f) ? -y : y + 1e-10f; // make sure y is not zero to prevent division by 0 - float z = abs_y / x; - float atan_approx; - - if (z < 1.0f) { - atan_approx = z / (1.0f + ATAN2_CONST_A * z * z); - if (x < 0.0f) { - return (y >= 0.0f) ? atan_approx + PI : atan_approx - PI; - } + float abs_y = fabs(y); + float abs_x = fabs(x); + float r = (abs_x - abs_y) / (abs_y + abs_x + 1e-10f); // avoid division by zero by adding a small nubmer + float angle; + if(x < 0) { + r = -r; + angle = M_PI/2.0f + M_PI/4.f; } - else { - z = x / abs_y; - atan_approx = M_PI_2 - z / (1.0f + ATAN2_CONST_A * z * z); - if (y < 0.0f) { - return -atan_approx; - } - } - return atan_approx; + else + angle = M_PI/2.0f - M_PI/4.f; + + float add = (ATAN2_CONST_A * (r * r) - ATAN2_CONST_B) * r; + angle += add; + angle = y < 0 ? -angle : angle; + return angle; } //https://stackoverflow.com/questions/3380628 From 98a6907976bfa3142545467359e876bd6d0ddc22 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 16 Oct 2024 19:53:58 +0200 Subject: [PATCH 04/52] cleanup and improvement to sin_appros() -replaced all PI references with M_PI version -there is no need to do the angle-modulo in float, casting it to an integer does the same BUT it has to be cast to an `int` first, see comment. --- wled00/wled_math.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 1825ab198..a191968e1 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -15,17 +15,17 @@ // Note: cos_t, sin_t and tan_t are very accurate but may be slow // the math.h functions use several kB of flash and are to be avoided if possible // sin16_t / cos16_t are faster and much more accurate than the fastled variants -// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy of +/-0.0015 compared to sinf() +// sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate float cos_t(float phi) { - float x = modd(phi, TWO_PI); + float x = modd(phi, M_TWOPI); if (x < 0) x = -1 * x; int8_t sign = 1; - if (x > PI) + if (x > M_PI) { - x -= PI; + x -= M_PI; sign = -1; } float xx = x * x; @@ -38,7 +38,7 @@ float cos_t(float phi) } float sin_t(float phi) { - float res = cos_t(HALF_PI - phi); + float res = cos_t(M_PI_2 - phi); #ifdef WLED_DEBUG_MATH Serial.printf("sin: %f,%f,%f,(%f)\n",x,res,sin(x),res-sin(x)); #endif @@ -87,9 +87,7 @@ uint8_t cos8_t(uint8_t theta) { float sin_approx(float theta) { - theta = modd(theta, TWO_PI); // modulo: bring to -2pi to 2pi range - if(theta < 0) theta += TWO_PI; // 0-2pi range - uint16_t scaled_theta = (uint16_t)(theta * (0xFFFF / TWO_PI)); + uint16_t scaled_theta = (int)(theta * (0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; @@ -118,10 +116,10 @@ float atan2_t(float y, float x) { float angle; if(x < 0) { r = -r; - angle = M_PI/2.0f + M_PI/4.f; + angle = M_PI_2 + M_PI_4; } else - angle = M_PI/2.0f - M_PI/4.f; + angle = M_PI_2 - M_PI_4; float add = (ATAN2_CONST_A * (r * r) - ATAN2_CONST_B) * r; angle += add; @@ -140,10 +138,10 @@ float acos_t(float x) { ret = ret * xabs; ret = ret - 0.2121144f; ret = ret * xabs; - ret = ret + HALF_PI; + ret = ret + M_PI_2; ret = ret * sqrt(1.0f-xabs); ret = ret - 2 * negate * ret; - float res = negate * PI + ret; + float res = negate * M_PI + ret; #ifdef WLED_DEBUG_MATH Serial.printf("acos: %f,%f,%f,(%f)\n",x,res,acos(x),res-acos(x)); #endif @@ -151,7 +149,7 @@ float acos_t(float x) { } float asin_t(float x) { - float res = HALF_PI - acos_t(x); + float res = M_PI_2 - acos_t(x); #ifdef WLED_DEBUG_MATH Serial.printf("asin: %f,%f,%f,(%f)\n",x,res,asin(x),res-asin(x)); #endif @@ -167,7 +165,7 @@ float atan_t(float x) { //For A/B/C, see https://stackoverflow.com/a/42542593 static const double A { 0.0776509570923569 }; static const double B { -0.287434475393028 }; - static const double C { ((HALF_PI/2) - A - B) }; + static const double C { ((M_PI_4) - A - B) }; // polynominal factors for approximation between 1 and 5 static const float C0 { 0.089494f }; static const float C1 { 0.974207f }; @@ -182,7 +180,7 @@ float atan_t(float x) { x = std::abs(x); float res; if (x > 5.0f) { // atan(x) converges to pi/2 - (1/x) for large values - res = HALF_PI - (1.0f/x); + res = M_PI_2 - (1.0f/x); } else if (x > 1.0f) { //1 < x < 5 float xx = x * x; res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0; From dcfdca63515f2d3f80674d05c6ee7186f9458354 Mon Sep 17 00:00:00 2001 From: ingDIY <10012263+ingDIY@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:14:37 +0200 Subject: [PATCH 05/52] cleaned up old references to USE_ALT_DISPlAY that aren't used anymore in the code/source files; fixed readme.md documents and updated instructions; removed referencies to old usermods; fixed invalid filenames; removed referencies to old usermods; checked cycle options; splitted and fixed platformio_override.sample.ini; --- platformio_override.sample.ini | 2 -- .../platformio_override.sample.ini} | 11 +++---- .../readme.md | 30 +++++-------------- .../platformio_override.sample.ini | 14 +++++++++ .../readme.md | 22 ++++---------- 5 files changed, 32 insertions(+), 47 deletions(-) rename usermods/{usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini => usermod_v2_four_line_display_ALT/platformio_override.sample.ini} (54%) create mode 100644 usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 8e5fdf003..c445cd32e 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -111,7 +111,6 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; ; Use 4 Line Display usermod with SPI display ; -D USERMOD_FOUR_LINE_DISPLAY -; -D USE_ALT_DISPlAY # mandatory ; -DFLD_SPI_DEFAULT ; -D FLD_TYPE=SSD1306_SPI64 ; -D FLD_PIN_CLOCKSPI=14 @@ -377,7 +376,6 @@ build_flags = ${common.build_flags} ${esp32.build_flags} -D USERMOD_DALLASTEMPERATURE -D USERMOD_FOUR_LINE_DISPLAY -D TEMPERATURE_PIN=23 - -D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI -D USERMOD_AUDIOREACTIVE lib_deps = ${esp32.lib_deps} OneWire@~2.3.5 diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini similarity index 54% rename from usermods/usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini rename to usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini index 6b32c71fb..9010648b3 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio–override.sample.ini +++ b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini @@ -7,11 +7,12 @@ platform = ${esp32.platform} build_unflags = ${common.build_unflags} build_flags = ${common.build_flags_esp32} - -D USERMOD_FOUR_LINE_DISPLAY -D USE_ALT_DISPlAY - -D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=18 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=19 -upload_speed = 460800 + -D USERMOD_FOUR_LINE_DISPLAY + -D FLD_TYPE=SH1106 + -D I2CSCLPIN=27 + -D I2CSDAPIN=26 + lib_deps = ${esp32.lib_deps} - U8g2@~2.34.4 + U8g2 Wire - diff --git a/usermods/usermod_v2_four_line_display_ALT/readme.md b/usermods/usermod_v2_four_line_display_ALT/readme.md index a8f386dac..39bb5d28e 100644 --- a/usermods/usermod_v2_four_line_display_ALT/readme.md +++ b/usermods/usermod_v2_four_line_display_ALT/readme.md @@ -1,16 +1,8 @@ # I2C/SPI 4 Line Display Usermod ALT -Thank you to the authors of the original version of these usermods. It would not have been possible without them! -"usermod_v2_four_line_display" -"usermod_v2_rotary_encoder_ui" +This usermod could be used in compination with `usermod_v2_rotary_encoder_ui_ALT`. -The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. -The display usermod UI has been completely changed. - - -The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. -Without the display, it functions identical to the original. -The original "usermod_v2_auto_save" will not work with the display just yet. +## Functionalities Press the encoder to cycle through the options: * Brightness @@ -18,26 +10,18 @@ Press the encoder to cycle through the options: * Intensity * Palette * Effect -* Main Color (only if display is used) -* Saturation (only if display is used) +* Main Color +* Saturation -Press and hold the encoder to display Network Info. If AP is active, it will display AP, SSID and password +Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password -Also shows if the timer is enabled +Also shows if the timer is enabled. [See the pair of usermods in action](https://www.youtube.com/watch?v=ulZnBt9z3TI) ## Installation -Please refer to the original `usermod_v2_rotary_encoder_ui` readme for the main instructions. - -Copy the example `platformio_override.sample.ini` from the usermod_v2_rotary_encoder_ui_ALT folder to the root directory of your particular build and rename it to `platformio_override.ini`. - -This file should be placed in the same directory as `platformio.ini`. - -Then, to activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, - or add `-D USE_ALT_DISPlAY` to the original `platformio_override.ini.sample` file - +Copy the example `platformio_override.sample.ini` to the root directory of your particular build. ## Configuration diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini b/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini new file mode 100644 index 000000000..8a88fd6b5 --- /dev/null +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/platformio_override.sample.ini @@ -0,0 +1,14 @@ +[platformio] +default_envs = esp32dev + +[env:esp32dev] +board = esp32dev +platform = ${esp32.platform} +build_unflags = ${common.build_unflags} +build_flags = + ${common.build_flags_esp32} + -D USERMOD_ROTARY_ENCODER_UI + -D USERMOD_ROTARY_ENCODER_GPIO=INPUT + -D ENCODER_DT_PIN=21 + -D ENCODER_CLK_PIN=23 + -D ENCODER_SW_PIN=0 diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md b/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md index 10db879fb..c46e87663 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/readme.md @@ -1,16 +1,8 @@ # Rotary Encoder UI Usermod ALT -Thank you to the authors of the original version of these usermods. It would not have been possible without them! -"usermod_v2_four_line_display" -"usermod_v2_rotary_encoder_ui" +This usermod supports the UI of the `usermod_v2_rotary_encoder_ui_ALT`. -The core of these usermods are a copy of the originals. The main changes are to the FourLineDisplay usermod. -The display usermod UI has been completely changed. - - -The changes made to the RotaryEncoder usermod were made to support the new UI in the display usermod. -Without the display, it functions identical to the original. -The original "usermod_v2_auto_save" will not work with the display just yet. +## Functionalities Press the encoder to cycle through the options: * Brightness @@ -21,8 +13,7 @@ Press the encoder to cycle through the options: * Main Color (only if display is used) * Saturation (only if display is used) -Press and hold the encoder to display Network Info - if AP is active, it will display the AP, SSID and Password +Press and hold the encoder to display Network Info. If AP is active, it will display the AP, SSID and Password Also shows if the timer is enabled. @@ -30,9 +21,7 @@ Also shows if the timer is enabled. ## Installation -Copy the example `platformio_override.sample.ini` to the root directory of your particular build and rename it to `platformio_override.ini`. - -To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE SENSITIVE) to the `usermods_list.cpp` file, or add `-D USE_ALT_DISPlAY` to your `platformio_override.ini` file +Copy the example `platformio_override.sample.ini` to the root directory of your particular build. ### Define Your Options @@ -40,7 +29,6 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE * `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details) -* `USE_ALT_DISPlAY` - Mandatory to use Four Line Display * `ENCODER_DT_PIN` - defaults to 18 * `ENCODER_CLK_PIN` - defaults to 5 * `ENCODER_SW_PIN` - defaults to 19 @@ -50,7 +38,7 @@ To activate this alternative usermod, add `#define USE_ALT_DISPlAY` (NOTE: CASE ### PlatformIO requirements -Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`. +No special requirements. ## Change Log From 798c398f23f9ea2c6e826acafa5a4a81ce35945a Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sat, 26 Oct 2024 20:33:38 +0200 Subject: [PATCH 06/52] specified required nodejs ver --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index d76d87687..0c016329b 100644 --- a/package.json +++ b/package.json @@ -27,5 +27,8 @@ "html-minifier-terser": "^7.2.0", "inliner": "^1.13.1", "nodemon": "^3.1.7" + }, + "engines": { + "node": ">=20.0.0" } } From 7c6bc5c4211c5c45342b2b833bf3d04991ee76ea Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sat, 26 Oct 2024 21:07:17 +0200 Subject: [PATCH 07/52] indened formating --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c016329b..35fda6002 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "nodemon": "^3.1.7" }, "engines": { - "node": ">=20.0.0" + "node": ">=21.0.0" } } From d05c358fd23d86697ec343b9c46c231d30346fcb Mon Sep 17 00:00:00 2001 From: maxi4329 Date: Sun, 27 Oct 2024 11:13:56 +0100 Subject: [PATCH 08/52] version changed to 20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35fda6002..0c016329b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "nodemon": "^3.1.7" }, "engines": { - "node": ">=21.0.0" + "node": ">=20.0.0" } } From fa053b7e60effbbb76dc49822003ea5acb4b4dcf Mon Sep 17 00:00:00 2001 From: ingDIY <10012263+ingDIY@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:14:02 +0100 Subject: [PATCH 09/52] Update platformio_override.sample.ini fixed back U8g2 version --- .../platformio_override.sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini index 9010648b3..e59637453 100644 --- a/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini +++ b/usermods/usermod_v2_four_line_display_ALT/platformio_override.sample.ini @@ -14,5 +14,5 @@ build_flags = lib_deps = ${esp32.lib_deps} - U8g2 + U8g2@~2.34.4 Wire From 1898be2fe1c9c3e9c05b5b41d2a2d9b597930156 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:13:43 +0100 Subject: [PATCH 10/52] S3 WROOM-2 buildenv this chip has 16MB or 32MB flash, and requires .memory_type = opi_opi --- platformio.ini | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platformio.ini b/platformio.ini index 9628722aa..48731f39b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -556,6 +556,32 @@ board_build.f_flash = 80000000L board_build.flash_mode = qio monitor_filters = esp32_exception_decoder +[env:esp32S3_wroom2] +;; For ESP32-S3 WROOM-2, a.k.a. ESP32-S3 DevKitC-1 v1.1 +;; with >= 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi) +platform = ${esp32s3.platform} +platform_packages = ${esp32s3.platform_packages} +board = esp32s3camlcd ;; this is the only standard board with "opi_opi" +board_build.arduino.memory_type = opi_opi +upload_speed = 921600 +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_WROOM-2 + -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 + -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip + ;; -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") + -DBOARD_HAS_PSRAM + -D LEDPIN=38 ;; buildin LED + -D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1 + ${esp32.AR_build_flags} + -D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4 ;; I2S mic +lib_deps = ${esp32s3.lib_deps} + ${esp32.AR_lib_deps} + +board_build.partitions = ${esp32.extreme_partitions} +board_upload.flash_size = 16MB +board_upload.maximum_size = 16777216 +monitor_filters = esp32_exception_decoder + [env:esp32s3_4M_qspi] ;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi) board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM From 749d34cd30a76e7c17be04f71016960d2331a4de Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:31:57 +0100 Subject: [PATCH 11/52] pinmanager support for S3 WROOM-2 (pin 33-37 reserved for flash) --- wled00/pin_manager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 793b5440c..0d4c2ad5c 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -201,7 +201,12 @@ bool PinManager::isPinOk(byte gpio, bool output) if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses. #endif if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH - if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM + #if CONFIG_ESPTOOLPY_FLASHMODE_OPI // 33-37: never available if using _octal_ Flash (opi_opi) + if (gpio > 32 && gpio < 38) return false; + #endif + #if CONFIG_SPIRAM_MODE_OCT // 33-37: not available if using _octal_ PSRAM (qio_opi), but free to use on _quad_ PSRAM (qio_qspi) + if (gpio > 32 && gpio < 38) return !psramFound(); + #endif // 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board. #elif defined(CONFIG_IDF_TARGET_ESP32S2) // strapping pins: 0, 45 & 46 From 3c2c5bedc50845c168f7e0881e3a1d6aa973e7d5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:42:54 +0100 Subject: [PATCH 12/52] LEDPIN --> DATA_PINS --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 48731f39b..6d4aa1dc1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -570,8 +570,9 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;; -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM - -D LEDPIN=38 ;; buildin LED + -D LEDPIN=38 -D DATA_PINS=38 ;; buildin WS2812b LED -D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1 + -D WLED_DEBUG ${esp32.AR_build_flags} -D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4 ;; I2S mic lib_deps = ${esp32s3.lib_deps} From d98ca9a202795f9851bbeca7e895cb790abd2727 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:51:46 +0100 Subject: [PATCH 13/52] show correct flash mode in WLED_DEBUG --- wled00/wled.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 13d43218a..d6a39a399 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -380,6 +380,12 @@ void WLED::setup() case FM_QOUT: DEBUG_PRINT(F("(QOUT)"));break; case FM_DIO: DEBUG_PRINT(F("(DIO)")); break; case FM_DOUT: DEBUG_PRINT(F("(DOUT)"));break; + #if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_ESPTOOLPY_FLASHMODE_OPI + case FM_FAST_READ: DEBUG_PRINT(F("(OPI)")); break; + #else + case FM_FAST_READ: DEBUG_PRINT(F("(fast_read)")); break; + #endif + case FM_SLOW_READ: DEBUG_PRINT(F("(slow_read)")); break; default: break; } #endif From 70323b947745e81644b955d3d16cc2bd24059636 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 2 Nov 2024 17:50:30 +0100 Subject: [PATCH 14/52] rename delay -> frameDelay Avoiding name collisions with the 'delay' function. --- wled00/FX_fcn.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 949b6a932..f45256f0f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1329,7 +1329,7 @@ void WS2812FX::service() { if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) { doShow = true; - unsigned delay = FRAMETIME; + unsigned frameDelay = FRAMETIME; if (!seg.freeze) { //only run effect function if not frozen int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based) @@ -1349,7 +1349,7 @@ void WS2812FX::service() { // overwritten by later effect. To enable seamless blending for every effect, additional LED buffer // would need to be allocated for each effect and then blended together for each pixel. [[maybe_unused]] uint8_t tmpMode = seg.currentMode(); // this will return old mode while in transition - delay = (*_mode[seg.mode])(); // run new/current mode + frameDelay = (*_mode[seg.mode])(); // run new/current mode #ifndef WLED_DISABLE_MODE_BLEND if (modeBlending && seg.mode != tmpMode) { Segment::tmpsegd_t _tmpSegData; @@ -1358,16 +1358,16 @@ void WS2812FX::service() { _virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed) unsigned d2 = (*_mode[tmpMode])(); // run old mode seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state) - delay = MIN(delay,d2); // use shortest delay + frameDelay = min(frameDelay,d2); // use shortest delay Segment::modeBlend(false); // unset semaphore } #endif seg.call++; - if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition + if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments } - seg.next_time = nowUp + delay; + seg.next_time = nowUp + frameDelay; } _segment_index++; } From bf37ac53a3dd5c666027932027502c72e69b6996 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 4 Nov 2024 08:10:05 +0100 Subject: [PATCH 15/52] improved FPS calc resolution, added averaging & multiplier compileflags Fixed point calculation for improved accuracy, dithering in debug builds only. Averaging and optional multiplier can be set as compile flags, example for speed testing with long averaging and a 10x multiplier: -D FPS_CALC_AVG=200 -D FPS_MULTIPLIER=10 The calculation resolution is limited (9.7bit fixed point) so values larger than 200 can hit resolution limit and get stuck before reaching the final value. If WLED_DEBUG is defined, dithering is added to the returned value so sub-frame accuracy is possible in post-processingwithout enabling the multiplier. --- wled00/FX.h | 10 +++++++++- wled00/FX_fcn.cpp | 16 +++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index ad39a7c06..1579a5bcb 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -47,6 +47,14 @@ #define FRAMETIME_FIXED (1000/WLED_FPS) #define FRAMETIME strip.getFrameTime() +// 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 + /* 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 @@ -729,7 +737,7 @@ class WS2812FX { // 96 bytes _transitionDur(750), _targetFps(WLED_FPS), _frametime(FRAMETIME_FIXED), - _cumulativeFps(2), + _cumulativeFps(50<<6), _isServicing(false), _isOffRefreshRequired(false), _hasWhiteChannel(false), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index f45256f0f..395451466 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1412,10 +1412,12 @@ void WS2812FX::show() { unsigned long showNow = millis(); size_t diff = showNow - _lastShow; - size_t fpsCurr = 200; - if (diff > 0) fpsCurr = 1000 / diff; - _cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5) - _lastShow = showNow; + + if (diff > 0) { // skip calculation if no time has passed + size_t fpsCurr = (1000<<7) / diff; // fixed point 9.7 bit + _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding + _lastShow = showNow; + } } /** @@ -1432,7 +1434,11 @@ bool WS2812FX::isUpdating() const { */ uint16_t WS2812FX::getFps() const { if (millis() - _lastShow > 2000) return 0; - return _cumulativeFps +1; + #ifdef WLED_DEBUG + return (FPS_MULTIPLIER * (_cumulativeFps + (random16() & 63))) >> 7; // + random("0.5") for dithering + #else + return (FPS_MULTIPLIER * _cumulativeFps) >> 7; // _cumulativeFps is stored in fixed point 9.7 bit + #endif } void WS2812FX::setTargetFps(uint8_t fps) { From 3733715184df2a684820a54f0d7caf61ab1dc0ac Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 4 Nov 2024 17:38:45 +0100 Subject: [PATCH 16/52] bugfix bitshift was still set from testing, forgot to update --- wled00/FX.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.h b/wled00/FX.h index 1579a5bcb..e5b7a0e95 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -737,7 +737,7 @@ class WS2812FX { // 96 bytes _transitionDur(750), _targetFps(WLED_FPS), _frametime(FRAMETIME_FIXED), - _cumulativeFps(50<<6), + _cumulativeFps(50<<7), _isServicing(false), _isOffRefreshRequired(false), _hasWhiteChannel(false), From 4634ace74e9e7295ff1518b449112146475df349 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 4 Nov 2024 19:33:42 +0100 Subject: [PATCH 17/52] Added define for bitshift, removed dithering dithering is not really needed, the FPS_MULTIPLIER is a much better option. --- wled00/FX.h | 3 ++- wled00/FX_fcn.cpp | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index e5b7a0e95..545161546 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -54,6 +54,7 @@ #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 */ @@ -737,7 +738,7 @@ class WS2812FX { // 96 bytes _transitionDur(750), _targetFps(WLED_FPS), _frametime(FRAMETIME_FIXED), - _cumulativeFps(50<<7), + _cumulativeFps(50 << FPS_CALC_SHIFT), _isServicing(false), _isOffRefreshRequired(false), _hasWhiteChannel(false), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 395451466..e706f2b43 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1414,7 +1414,7 @@ void WS2812FX::show() { size_t diff = showNow - _lastShow; if (diff > 0) { // skip calculation if no time has passed - size_t fpsCurr = (1000<<7) / diff; // fixed point 9.7 bit + size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding _lastShow = showNow; } @@ -1434,11 +1434,7 @@ bool WS2812FX::isUpdating() const { */ uint16_t WS2812FX::getFps() const { if (millis() - _lastShow > 2000) return 0; - #ifdef WLED_DEBUG - return (FPS_MULTIPLIER * (_cumulativeFps + (random16() & 63))) >> 7; // + random("0.5") for dithering - #else - return (FPS_MULTIPLIER * _cumulativeFps) >> 7; // _cumulativeFps is stored in fixed point 9.7 bit - #endif + return (FPS_MULTIPLIER * _cumulativeFps) >> FPS_CALC_SHIFT; // _cumulativeFps is stored in fixed point } void WS2812FX::setTargetFps(uint8_t fps) { From 536444f9d1fae4c092a6cfd2f3d944e31cf30055 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 9 Nov 2024 16:38:18 +0100 Subject: [PATCH 18/52] fixed palette FX to more closely match original 1D version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rotation scale is now exactly 180° (divide slider input by 255 instead of 256) - removed shift offset: offset is now zero at slider 0, to hit 128 on touch input devices is really hard - added a 90° shift to input rotation, enabling to rotate from 0 to 180° instead of +90 to -90 (which is not useful in 1D) - changed default settings values to more closely match the old 1D effect --- wled00/FX.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2f24f745a..47200655d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1940,7 +1940,7 @@ uint16_t mode_palette() { using angleType = unsigned; constexpr mathType sInt16Scale = 0x7FFF; constexpr mathType maxAngle = 0x8000; - constexpr mathType staticRotationScale = 256; + constexpr mathType staticRotationScale = 255; constexpr mathType animatedRotationScale = 1; constexpr int16_t (*sinFunction)(uint16_t) = &sin16; constexpr int16_t (*cosFunction)(uint16_t) = &cos16; @@ -1949,7 +1949,7 @@ uint16_t mode_palette() { using wideMathType = float; using angleType = float; constexpr mathType sInt16Scale = 1.0f; - constexpr mathType maxAngle = M_PI / 256.0; + constexpr mathType maxAngle = M_PI / 255.0; constexpr mathType staticRotationScale = 1.0f; constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF); constexpr float (*sinFunction)(float) = &sin_t; @@ -1961,7 +1961,7 @@ uint16_t mode_palette() { const int inputShift = SEGMENT.speed; const int inputSize = SEGMENT.intensity; - const int inputRotation = SEGMENT.custom1; + const int inputRotation = SEGMENT.custom1 + 128; const bool inputAnimateShift = SEGMENT.check1; const bool inputAnimateRotation = SEGMENT.check2; const bool inputAssumeSquare = SEGMENT.check3; @@ -1985,7 +1985,7 @@ uint16_t mode_palette() { // So the rectangle needs to have exactly the right size. That size depends on the rotation. // This scale computation here only considers one dimension. You can think of it like the rectangle is always scaled so that // the left and right most points always match the left and right side of the display. - const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut); + const mathType scale = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut); // 2D simulation: // If we are dealing with a 1D setup, we assume that each segment represents one line on a 2-dimensional display. // The function is called once per segments, so we need to handle one line at a time. @@ -2016,7 +2016,7 @@ uint16_t mode_palette() { colorIndex = ((inputSize - 112) * colorIndex) / 16; } // Finally, shift the palette a bit. - const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); + const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); colorIndex += paletteOffset; const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex); if (isMatrix) { @@ -2028,7 +2028,7 @@ uint16_t mode_palette() { } return FRAMETIME; } -static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0"; +static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;ix=112,c1=0,o1=1,o2=0,o3=1"; // WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active From 5de86d3d9166e1d629d5fdcd128008360378dccd Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:55:09 +0100 Subject: [PATCH 19/52] fix problem with spaces --- tools/cdata.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cdata.js b/tools/cdata.js index d65573a8e..c5d3c6aa5 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -101,6 +101,7 @@ function adoptVersionAndRepo(html) { async function minify(str, type = "plain") { const options = { collapseWhitespace: true, + conservativeCollapse: true, // preserve spaces in text collapseBooleanAttributes: true, collapseInlineTagWhitespace: true, minifyCSS: true, From 223b97b8848d8f44c891ea511dadc20e40270cf7 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sun, 10 Nov 2024 18:04:07 -0500 Subject: [PATCH 20/52] handleSet: Fix incorrect response generation Don't generate a response if there's no HTTP request. Fixes #4269 --- wled00/set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/set.cpp b/wled00/set.cpp index c446a2eff..712e5f254 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -1191,7 +1191,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) // internal call, does not send XML response pos = req.indexOf(F("IN")); - if (pos < 1) { + if ((request != nullptr) && (pos < 1)) { auto response = request->beginResponseStream("text/xml"); XML_response(*response); request->send(response); From 8c5e0cd4e94ebc4a2d59c24fce620f6e3540c903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 15 Nov 2024 16:01:58 +0100 Subject: [PATCH 21/52] Keep selected FX while searching --- wled00/data/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index d9c64bdfb..cbc389391 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2850,7 +2850,7 @@ function search(field, listId = null) { if (listId!=='pcont' && i===0) return; const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); - listItem.style.display = (searchIndex < 0) ? 'none' : ''; + listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; listItem.dataset.searchIndex = searchIndex; }); @@ -2924,7 +2924,7 @@ function filterFx() { const listItemName = listItem.querySelector('.lstIname').innerText; let hide = false; gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); - listItem.style.display = hide ? 'none' : ''; + listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : ''; }); } From 86be5df475468824cee3654efc6175170d3dbf83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 15 Nov 2024 19:03:46 +0100 Subject: [PATCH 22/52] xml comma bugfix + few optimisations --- wled00/xml.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..a4a72abea 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -83,7 +83,7 @@ void appendGPIOinfo(Print& settingsScript) { // usermod pin reservations will become unnecessary when settings pages will read cfg.json directly if (requestJSONBufferLock(6)) { // if we can't allocate JSON buffer ignore usermod pins - JsonObject mods = pDoc->createNestedObject(F("um")); + JsonObject mods = pDoc->createNestedObject("um"); UsermodManager::addToConfig(mods); if (!mods.isNull()) fillUMPins(settingsScript, mods); releaseJSONBufferLock(); @@ -91,35 +91,42 @@ void appendGPIOinfo(Print& settingsScript) { settingsScript.print(F("];")); // add reserved (unusable) pins + bool firstPin = true; settingsScript.print(F("d.rsvd=[")); for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (!PinManager::isPinOk(i, false)) { // include readonly pins - settingsScript.print(i); settingsScript.print(","); + if (!firstPin) settingsScript.print(','); + settingsScript.print(i); + firstPin = false; } } #ifdef WLED_ENABLE_DMX - settingsScript.print(F("2,")); // DMX hardcoded pin + if (!firstPin) settingsScript.print(','); + settingsScript.print(2); // DMX hardcoded pin + firstPin = false; #endif #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) - settingsScript.printf_P(PSTR(",%d"),hardwareTX); // debug output (TX) pin + if (!firstPin) settingsScript.print(','); + settingsScript.print(hardwareTX); // debug output (TX) pin + firstPin = false; #endif - //Note: Using pin 3 (RX) disables Adalight / Serial JSON #ifdef WLED_USE_ETHERNET if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { - for (unsigned p=0; p=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_power); } - if (ethernetBoards[ethernetType].eth_mdc>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdc); } - if (ethernetBoards[ethernetType].eth_mdio>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdio); } - switch (ethernetBoards[ethernetType].eth_clk_mode) { + if (!firstPin) settingsScript.print(','); + for (unsigned p=0; p= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_power); } + if (ethernetBoards[ethernetType].eth_mdc >= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdc); } + if (ethernetBoards[ethernetType].eth_mdio >= 0) { settingsScript.printf("%d,",ethernetBoards[ethernetType].eth_mdio); } + switch (ethernetBoards[ethernetType].eth_clk_mode) { case ETH_CLOCK_GPIO0_IN: case ETH_CLOCK_GPIO0_OUT: - settingsScript.print(F("0")); + settingsScript.print(0); break; case ETH_CLOCK_GPIO16_OUT: - settingsScript.print(F("16")); + settingsScript.print(16); break; case ETH_CLOCK_GPIO17_OUT: - settingsScript.print(F("17")); + settingsScript.print(17); break; } } @@ -128,11 +135,11 @@ void appendGPIOinfo(Print& settingsScript) { // add info for read-only GPIO settingsScript.print(F("d.ro_gpio=[")); - bool firstPin = true; + firstPin = true; for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (PinManager::isReadOnlyPin(i)) { // No comma before the first pin - if (!firstPin) settingsScript.print(F(",")); + if (!firstPin) settingsScript.print(','); settingsScript.print(i); firstPin = false; } @@ -142,7 +149,7 @@ void appendGPIOinfo(Print& settingsScript) { // add info about max. # of pins settingsScript.print(F("d.max_gpio=")); settingsScript.print(WLED_NUM_PINS); - settingsScript.print(F(";")); + settingsScript.print(';'); } //get values for settings form in javascript @@ -152,6 +159,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) DEBUG_PRINTF_P(PSTR("settings resp %u\n"), (unsigned)subPage); if (subPage <0 || subPage >10) return; + char nS[32]; if (subPage == SUBPAGE_MENU) { @@ -259,8 +267,6 @@ void getSettingsJS(byte subPage, Print& settingsScript) if (subPage == SUBPAGE_LEDS) { - char nS[32]; - appendGPIOinfo(settingsScript); settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); @@ -399,7 +405,6 @@ void getSettingsJS(byte subPage, Print& settingsScript) if (subPage == SUBPAGE_SYNC) { - [[maybe_unused]] char nS[32]; printSetFormValue(settingsScript,PSTR("UP"),udpPort); printSetFormValue(settingsScript,PSTR("U2"),udpPort2); #ifndef WLED_DISABLE_ESPNOW @@ -637,7 +642,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) #if defined(ARDUINO_ARCH_ESP32) ESP.getChipModel(), #else - F("esp8266"), + "esp8266", #endif VERSION); From 6fe2024542b12fc17af98fa6402ca5f557a6d958 Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:53:10 +0100 Subject: [PATCH 23/52] move selected to the bottom in search result --- wled00/data/index.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index cbc389391..f93511aaf 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2827,7 +2827,7 @@ function search(field, listId = null) { // restore default preset sorting if no search term is entered if (!search) { - if (listId === 'pcont') { populatePresets(); return; } + if (listId === 'pcont') { populatePresets(); return; } if (listId === 'pallist') { let id = parseInt(d.querySelector('#pallist input[name="palette"]:checked').value); // preserve selected palette populatePalettes(); @@ -2846,12 +2846,17 @@ function search(field, listId = null) { // filter list items but leave (Default & Solid) always visible const listItems = gId(listId).querySelectorAll('.lstI'); - listItems.forEach((listItem,i)=>{ - if (listId!=='pcont' && i===0) return; + listItems.forEach((listItem, i) => { const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); - listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; - listItem.dataset.searchIndex = searchIndex; + if (searchIndex < 0) { + listItem.dataset.searchIndex = Number.MAX_SAFE_INTEGER; + } else { + listItem.dataset.searchIndex = searchIndex; + } + + if ((listId !== 'pcont' && i === 0) || listItem.classList.contains("selected")) return; + listItem.style.display = (searchIndex < 0) ? 'none' : ''; }); // sort list items by search index and name @@ -2920,10 +2925,10 @@ function filterFx() { inputField.value = ''; inputField.focus(); clean(inputField.nextElementSibling); - gId("fxlist").querySelectorAll('.lstI').forEach((listItem,i) => { + gId("fxlist").querySelectorAll('.lstI').forEach((listItem, i) => { const listItemName = listItem.querySelector('.lstIname').innerText; let hide = false; - gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); + gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i > 0 /*true*/; }); listItem.style.display = hide && !listItem.classList.contains("selected") ? 'none' : ''; }); } From 4d3df5d98fb283e936db9eb7f19406a3a5a38b24 Mon Sep 17 00:00:00 2001 From: Woody <27882680+w00000dy@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:12:29 +0100 Subject: [PATCH 24/52] Fix default/solid not being first --- wled00/data/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index f93511aaf..1482c27b5 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2847,6 +2847,7 @@ function search(field, listId = null) { // filter list items but leave (Default & Solid) always visible const listItems = gId(listId).querySelectorAll('.lstI'); listItems.forEach((listItem, i) => { + if (listId !== 'pcont' && i === 0) return; const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); if (searchIndex < 0) { @@ -2854,9 +2855,7 @@ function search(field, listId = null) { } else { listItem.dataset.searchIndex = searchIndex; } - - if ((listId !== 'pcont' && i === 0) || listItem.classList.contains("selected")) return; - listItem.style.display = (searchIndex < 0) ? 'none' : ''; + listItem.style.display = (searchIndex < 0) && !listItem.classList.contains("selected") ? 'none' : ''; }); // sort list items by search index and name From a765903a41d3272c166ff5351da5c0338947c183 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 16 Nov 2024 17:10:08 -0500 Subject: [PATCH 25/52] Fix array overflow in exploding_fireworks Attempt to allocate enough room for the "minimum" sparks; and ensure that we never overrun the allocated array size. Fixes #4120 --- wled00/FX.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2f24f745a..947788fee 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3547,7 +3547,7 @@ uint16_t mode_exploding_fireworks(void) if (segs <= (strip.getMaxSegments() /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg - unsigned numSparks = min(2 + ((rows*cols) >> 1), maxSparks); + unsigned numSparks = min(5 + ((rows*cols) >> 1), maxSparks); unsigned dataSize = sizeof(spark) * numSparks; if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed float *dying_gravity = reinterpret_cast(SEGENV.data + dataSize); @@ -3602,7 +3602,8 @@ uint16_t mode_exploding_fireworks(void) * Size is proportional to the height. */ unsigned nSparks = flare->pos + random8(4); - nSparks = constrain(nSparks, 4, numSparks); + nSparks = std::max(nSparks, 4U); // This is not a standard constrain; numSparks is not guaranteed to be at least 4 + nSparks = std::min(nSparks, numSparks); // initialize sparks if (SEGENV.aux0 == 2) { From 84dd26c1b7d90b2f4466253bc9e6b9faa545451a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Sun, 17 Nov 2024 10:47:09 +0100 Subject: [PATCH 26/52] Some more optimisations. --- wled00/xml.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index a4a72abea..df52b6248 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -147,9 +147,7 @@ void appendGPIOinfo(Print& settingsScript) { settingsScript.print(F("];")); // add info about max. # of pins - settingsScript.print(F("d.max_gpio=")); - settingsScript.print(WLED_NUM_PINS); - settingsScript.print(';'); + settingsScript.printf_P(PSTR("d.max_gpio=%d;"),WLED_NUM_PINS); } //get values for settings form in javascript @@ -269,7 +267,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) { appendGPIOinfo(settingsScript); - settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); + settingsScript.printf_P(PSTR("d.ledTypes=%s;"), BusManager::getLEDTypesJSONString().c_str()); // set limits settingsScript.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"), @@ -653,8 +651,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) { printSetFormValue(settingsScript,PSTR("SOMP"),strip.isMatrix); #ifndef WLED_DISABLE_2D - settingsScript.printf_P(PSTR("maxPanels=%d;"),WLED_MAX_PANELS); - settingsScript.print(F("resetPanels();")); + settingsScript.printf_P(PSTR("maxPanels=%d;resetPanels();"),WLED_MAX_PANELS); if (strip.isMatrix) { if(strip.panels>0){ printSetFormValue(settingsScript,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience @@ -664,11 +661,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) // panels for (unsigned i=0; i Date: Sun, 17 Nov 2024 14:31:23 +0100 Subject: [PATCH 27/52] Bugfix --- wled00/xml.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index df52b6248..597db73f2 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -660,8 +660,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MPC"),strip.panels); // panels for (unsigned i=0; i Date: Thu, 21 Nov 2024 10:52:22 +0100 Subject: [PATCH 28/52] Introduce printSetInputMaxlength to properly set an inputs maxlength variable --- wled00/fcn_declare.h | 1 + wled00/util.cpp | 4 ++++ wled00/xml.cpp | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 1855a8b63..91176160f 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -380,6 +380,7 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val); size_t printSetFormValue(Print& settingsScript, const char* key, const char* val); size_t printSetFormIndex(Print& settingsScript, const char* key, int index); size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val); +size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val); void prepareHostname(char* hostname); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); diff --git a/wled00/util.cpp b/wled00/util.cpp index 0b78a4646..1c1282eda 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -109,6 +109,10 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in return settingsScript.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val); } +size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val) { + return settingsScript.printf_P(PSTR("d.Sf.%s.setAttribute(\"maxlength\", %d);"),key,val); +} + void prepareHostname(char* hostname) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..6f837a9b6 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,8 +465,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), - MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); + printSetInputMaxLength(settingsScript, PSTR("MD"), MQTT_MAX_TOPIC_LEN); + printSetInputMaxLength(settingsScript, PSTR("MG"), MQTT_MAX_TOPIC_LEN); + printSetInputMaxLength(settingsScript, PSTR("MS"), MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings #endif From 5ac8ba9bae80688ab9c9151e8775447d8e86cbf1 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 21 Nov 2024 12:02:55 +0100 Subject: [PATCH 29/52] Revert "Introduce printSetInputMaxlength to properly set an inputs maxlength variable" This reverts commit 49fb16e2c6528ddc98cccc352cc8f0d4a5f62a13. --- wled00/fcn_declare.h | 1 - wled00/util.cpp | 4 ---- wled00/xml.cpp | 5 ++--- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 91176160f..1855a8b63 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -380,7 +380,6 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val); size_t printSetFormValue(Print& settingsScript, const char* key, const char* val); size_t printSetFormIndex(Print& settingsScript, const char* key, int index); size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val); -size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val); void prepareHostname(char* hostname); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); diff --git a/wled00/util.cpp b/wled00/util.cpp index 1c1282eda..0b78a4646 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -109,10 +109,6 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in return settingsScript.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val); } -size_t printSetInputMaxLength(Print& settingsScript, const char* key, int val) { - return settingsScript.printf_P(PSTR("d.Sf.%s.setAttribute(\"maxlength\", %d);"),key,val); -} - void prepareHostname(char* hostname) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 6f837a9b6..dc2673271 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,9 +465,8 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - printSetInputMaxLength(settingsScript, PSTR("MD"), MQTT_MAX_TOPIC_LEN); - printSetInputMaxLength(settingsScript, PSTR("MG"), MQTT_MAX_TOPIC_LEN); - printSetInputMaxLength(settingsScript, PSTR("MS"), MQTT_MAX_SERVER_LEN); + settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), + MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings #endif From 5c8b2ebf7a015983890daecabe0db1cfcc7628d0 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 21 Nov 2024 12:04:01 +0100 Subject: [PATCH 30/52] maxlength -> maxLength to fix this attribute not being modified correctly --- wled00/xml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index dc2673271..0893e5d25 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -465,7 +465,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); - settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), + settingsScript.printf_P(PSTR("d.Sf.MD.maxLength=%d;d.Sf.MG.maxLength=%d;d.Sf.MS.maxLength=%d;"), MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); #else settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings From 548736f432d5c1484b85045816ce1cfbafaa4e46 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:50:55 +0100 Subject: [PATCH 31/52] SparkFunDMX fix for possible array bounds violation in DMX.write Align with code in espdmx.cpp --- wled00/src/dependencies/dmx/SparkFunDMX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/src/dependencies/dmx/SparkFunDMX.cpp b/wled00/src/dependencies/dmx/SparkFunDMX.cpp index dbc9b1590..064b9ff62 100644 --- a/wled00/src/dependencies/dmx/SparkFunDMX.cpp +++ b/wled00/src/dependencies/dmx/SparkFunDMX.cpp @@ -34,8 +34,8 @@ static const int enablePin = -1; // disable the enable pin because it is not ne static const int rxPin = -1; // disable the receiving pin because it is not needed - softhack007: Pin=-1 means "use default" not "disable" static const int txPin = 2; // transmit DMX data over this pin (default is pin 2) -//DMX value array and size. Entry 0 will hold startbyte -static uint8_t dmxData[dmxMaxChannel] = { 0 }; +//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements +static uint8_t dmxData[dmxMaxChannel+1] = { 0 }; static int chanSize = 0; #if !defined(DMX_SEND_ONLY) static int currentChannel = 0; From 32dc54ce7239c9947260db272750fb5c5cfacb19 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Fri, 22 Nov 2024 08:43:45 +0100 Subject: [PATCH 32/52] reverted rotation scale, offset only on static rotation, inverted shift direction - inverting the shift direction in signed int is computationally safe as it is cast into an uint8_t and it matches the original FX in 1D --- wled00/FX.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 47200655d..1463121eb 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1940,7 +1940,7 @@ uint16_t mode_palette() { using angleType = unsigned; constexpr mathType sInt16Scale = 0x7FFF; constexpr mathType maxAngle = 0x8000; - constexpr mathType staticRotationScale = 255; + constexpr mathType staticRotationScale = 256; constexpr mathType animatedRotationScale = 1; constexpr int16_t (*sinFunction)(uint16_t) = &sin16; constexpr int16_t (*cosFunction)(uint16_t) = &cos16; @@ -1949,7 +1949,7 @@ uint16_t mode_palette() { using wideMathType = float; using angleType = float; constexpr mathType sInt16Scale = 1.0f; - constexpr mathType maxAngle = M_PI / 255.0; + constexpr mathType maxAngle = M_PI / 256.0; constexpr mathType staticRotationScale = 1.0f; constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF); constexpr float (*sinFunction)(float) = &sin_t; @@ -1961,12 +1961,12 @@ uint16_t mode_palette() { const int inputShift = SEGMENT.speed; const int inputSize = SEGMENT.intensity; - const int inputRotation = SEGMENT.custom1 + 128; + const int inputRotation = SEGMENT.custom1; const bool inputAnimateShift = SEGMENT.check1; const bool inputAnimateRotation = SEGMENT.check2; const bool inputAssumeSquare = SEGMENT.check3; - const angleType theta = (!inputAnimateRotation) ? (inputRotation * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale); + const angleType theta = (!inputAnimateRotation) ? ((inputRotation + 128) * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale); const mathType sinTheta = sinFunction(theta); const mathType cosTheta = cosFunction(theta); @@ -2017,7 +2017,7 @@ uint16_t mode_palette() { } // Finally, shift the palette a bit. const int paletteOffset = (!inputAnimateShift) ? (inputShift) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8); - colorIndex += paletteOffset; + colorIndex -= paletteOffset; const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex); if (isMatrix) { SEGMENT.setPixelColorXY(x, y, color); From 6aef0e145c234cabb1129feed4068830de45a409 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 23 Nov 2024 16:31:07 +0000 Subject: [PATCH 33/52] Remove TOSTRING for releaseString and add quotes to WLED_RELEASE_NAME --- platformio.ini | 42 +++++++++++++++++++++--------------------- wled00/wled.h | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6d4aa1dc1..fe02213ff 100644 --- a/platformio.ini +++ b/platformio.ini @@ -345,7 +345,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_4m1m} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266\" #-DWLED_DISABLE_2D lib_deps = ${esp8266.lib_deps} monitor_filters = esp8266_exception_decoder @@ -354,13 +354,13 @@ extends = env:nodemcuv2 ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP8266_compat #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP8266_compat\" #-DWLED_DISABLE_2D ;; lib_deps = ${esp8266.lib_deps_compat} ;; experimental - use older NeoPixelBus 2.7.9 [env:nodemcuv2_160] extends = env:nodemcuv2 board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP8266_160 #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_160\" #-DWLED_DISABLE_2D -D USERMOD_AUDIOREACTIVE [env:esp8266_2m] @@ -369,7 +369,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_2m512k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02 +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02\" lib_deps = ${esp8266.lib_deps} [env:esp8266_2m_compat] @@ -377,12 +377,12 @@ extends = env:esp8266_2m ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP02_compat #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP02_compat\" #-DWLED_DISABLE_2D [env:esp8266_2m_160] extends = env:esp8266_2m board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP02_160 +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02_160\" -D USERMOD_AUDIOREACTIVE [env:esp01_1m_full] @@ -391,7 +391,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_1m128k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01\" -D WLED_DISABLE_OTA ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM lib_deps = ${esp8266.lib_deps} @@ -400,12 +400,12 @@ extends = env:esp01_1m_full ;; using platform version and build options from WLED 0.14.0 platform = ${esp8266.platform_compat} platform_packages = ${esp8266.platform_packages_compat} -build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=ESP01_compat -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D +build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEASE_NAME=\"ESP01_compat\" -D WLED_DISABLE_OTA #-DWLED_DISABLE_2D [env:esp01_1m_full_160] extends = env:esp01_1m_full board_build.f_cpu = 160000000L -build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=ESP01_160 -D WLED_DISABLE_OTA +build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01_160\" -D WLED_DISABLE_OTA -D USERMOD_AUDIOREACTIVE ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM @@ -414,7 +414,7 @@ board = esp32dev platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} ${esp32.AR_lib_deps} @@ -426,7 +426,7 @@ board = esp32dev platform = ${esp32_idf_V4.platform} platform_packages = ${esp32_idf_V4.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_8M #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} ${esp32.AR_lib_deps} @@ -442,7 +442,7 @@ board = esp32dev platform = ${esp32_idf_V4.platform} platform_packages = ${esp32_idf_V4.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_16M #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} ${esp32.AR_lib_deps} @@ -458,7 +458,7 @@ board_build.flash_mode = dio ;platform = ${esp32.platform} ;platform_packages = ${esp32.platform_packages} ;build_unflags = ${common.build_unflags} -;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_audioreactive #-D WLED_DISABLE_BROWNOUT_DET +;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_audioreactive\" #-D WLED_DISABLE_BROWNOUT_DET ; ${esp32.AR_build_flags} ;lib_deps = ${esp32.lib_deps} ; ${esp32.AR_lib_deps} @@ -473,7 +473,7 @@ platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 +build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 ; -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} @@ -489,7 +489,7 @@ board_build.f_flash = 80000000L board_build.flash_mode = qio board_build.partitions = ${esp32.extended_partitions} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_WROVER +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\" -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html -D DATA_PINS=25 ${esp32.AR_build_flags} @@ -503,7 +503,7 @@ platform_packages = ${esp32c3.platform_packages} framework = arduino board = esp32-c3-devkitm-1 board_build.partitions = ${esp32.default_partitions} -build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=ESP32-C3 +build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C3\" -D WLED_WATCHDOG_TIMEOUT=0 -DLOLIN_WIFI_FIX ; seems to work much better with this -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB @@ -520,7 +520,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_16MB_opi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_16MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -543,7 +543,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_opi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -565,7 +565,7 @@ board = esp32s3camlcd ;; this is the only standard board with "opi_opi" board_build.arduino.memory_type = opi_opi upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_WROOM-2 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip ;; -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") @@ -590,7 +590,7 @@ platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_4M_qspi +build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_4M_qspi\" -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM -DLOLIN_WIFI_FIX ; seems to work much better with this @@ -611,7 +611,7 @@ board_build.partitions = ${esp32.default_partitions} board_build.flash_mode = qio board_build.f_flash = 80000000L build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2 +build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\" -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 diff --git a/wled00/wled.h b/wled00/wled.h index 2b3a77d24..163ce6b04 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -269,7 +269,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; // Global Variable definitions WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); -WLED_GLOBAL char releaseString[] _INIT(TOSTRING(WLED_RELEASE_NAME)); // somehow this will not work if using "const char releaseString[] +WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // somehow this will not work if using "const char releaseString[] #define WLED_CODENAME "Kōsen" // AP and OTA default passwords (for maximum security change them!) From 0be1df7ee89d01a53b0043dd4c4b66c0e741ccd4 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 23 Nov 2024 16:46:41 +0000 Subject: [PATCH 34/52] Stip \" from WLED_RELEASE_NAME --- pio-scripts/output_bins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pio-scripts/output_bins.py b/pio-scripts/output_bins.py index 633654008..bdd6fc941 100644 --- a/pio-scripts/output_bins.py +++ b/pio-scripts/output_bins.py @@ -19,7 +19,7 @@ def _create_dirs(dirs=["map", "release", "firmware"]): os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) def create_release(source): - release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME") + release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME").replace("\\\"", "") if release_name: version = _get_cpp_define_value(env, "WLED_VERSION") release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") From d53d7aa2e2d22085979e0134fb7ce1c5dd6684df Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 23 Nov 2024 12:29:46 -0500 Subject: [PATCH 35/52] Defer calling begin() on digital buses NeoPixelBus requires that all parallel I2S bus members be constructed before any of them call Begin(). Implement this by deferring the call to the end of bus construction. Fixes #4301. --- wled00/FX_fcn.cpp | 11 +++-------- wled00/bus_manager.cpp | 4 ++-- wled00/bus_manager.h | 3 ++- wled00/bus_wrapper.h | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e706f2b43..7177ca89e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1286,14 +1286,9 @@ void WS2812FX::finalizeInit() { _isOffRefreshRequired |= bus->isOffRefreshRequired() && !bus->isPWM(); // use refresh bit for phase shift with analog unsigned busEnd = bus->getStart() + bus->getLength(); if (busEnd > _length) _length = busEnd; - #ifdef ESP8266 - // why do we need to reinitialise GPIO3??? - //if (!bus->isDigital() || bus->is2Pin()) continue; - //uint8_t pins[5]; - //if (!bus->getPins(pins)) continue; - //BusDigital* bd = static_cast(bus); - //if (pins[0] == 3) bd->reinit(); - #endif + + // This must be done after all buses have been created, as some kinds (parallel I2S) interact + bus->begin(); } Segment::maxWidth = _length; diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 5b948b9c4..8281211c1 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -410,7 +410,7 @@ std::vector BusDigital::getLEDTypes() { }; } -void BusDigital::reinit() { +void BusDigital::begin() { if (!_valid) return; PolyBus::begin(_busPtr, _iType, _pins); } @@ -910,7 +910,7 @@ void BusManager::on() { if (busses[i]->isDigital() && busses[i]->getPins(pins)) { if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) { BusDigital *bus = static_cast(busses[i]); - bus->reinit(); + bus->begin(); break; } } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index e96b9de71..ecebc120e 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -79,6 +79,7 @@ class Bus { virtual ~Bus() {} //throw the bus under the bus + virtual void begin() {}; virtual void show() = 0; virtual bool canShow() const { return true; } virtual void setStatusPixel(uint32_t c) {} @@ -213,7 +214,7 @@ class BusDigital : public Bus { uint16_t getLEDCurrent() const override { return _milliAmpsPerLed; } uint16_t getUsedCurrent() const override { return _milliAmpsTotal; } uint16_t getMaxCurrent() const override { return _milliAmpsMax; } - void reinit(); + void begin() override; void cleanup(); static std::vector getLEDTypes(); diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 84c32f46b..7e6e74d85 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -597,7 +597,7 @@ class PolyBus { case I_HS_P98_3: busPtr = new B_HS_P98_3(len, pins[1], pins[0]); break; case I_SS_P98_3: busPtr = new B_SS_P98_3(len, pins[1], pins[0]); break; } - begin(busPtr, busType, pins, clock_kHz); + return busPtr; } From 0c77dbb7ea63c0b228d5d0f576d6eb0dcb7daeb1 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 24 Nov 2024 13:55:23 +0000 Subject: [PATCH 36/52] cleanup WLED_RELEASE_NAME only if present --- pio-scripts/output_bins.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pio-scripts/output_bins.py b/pio-scripts/output_bins.py index bdd6fc941..4d1594d84 100644 --- a/pio-scripts/output_bins.py +++ b/pio-scripts/output_bins.py @@ -19,8 +19,9 @@ def _create_dirs(dirs=["map", "release", "firmware"]): os.makedirs(os.path.join(OUTPUT_DIR, d), exist_ok=True) def create_release(source): - release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME").replace("\\\"", "") - if release_name: + release_name_def = _get_cpp_define_value(env, "WLED_RELEASE_NAME") + if release_name_def: + release_name = release_name_def.replace("\\\"", "") version = _get_cpp_define_value(env, "WLED_VERSION") release_file = os.path.join(OUTPUT_DIR, "release", f"WLED_{version}_{release_name}.bin") release_gz_file = release_file + ".gz" From 20f8d3c8a9cc0812261089714baaf08538aabb19 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 24 Nov 2024 15:26:30 +0000 Subject: [PATCH 37/52] Builds without WLED_RELEASE_NAME should be called Custom --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index 163ce6b04..bb647340b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -264,7 +264,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; #define WLED_VERSION dev #endif #ifndef WLED_RELEASE_NAME - #define WLED_RELEASE_NAME dev_release + #define WLED_RELEASE_NAME "Custom" #endif // Global Variable definitions From 5b989adebc666f5d6314e0ece81c1141a0ae454f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:27:53 +0100 Subject: [PATCH 38/52] Allow TV Simulator on single LED segments I've checked the code - nothing preventing the effect to run with SEGLEN=1 --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 947788fee..80be13c62 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4631,7 +4631,7 @@ uint16_t mode_tv_simulator(void) { return FRAMETIME; } -static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;"; +static const char _data_FX_MODE_TV_SIMULATOR[] PROGMEM = "TV Simulator@!,!;;!;01"; /* From dd533a9ab4f37c8bc271f4a7cdbd7c0fe51456a3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Mon, 25 Nov 2024 23:00:31 +0000 Subject: [PATCH 39/52] Update sample WLED_RELEASE_NAME --- platformio_override.sample.ini | 2 +- wled00/wled.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 8e5fdf003..a4dea6677 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -37,7 +37,7 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; *** To use the below defines/overrides, copy and paste each onto it's own line just below build_flags in the section above. ; ; Set a release name that may be used to distinguish required binary for flashing -; -D WLED_RELEASE_NAME=ESP32_MULTI_USREMODS +; -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" ; ; disable specific features ; -D WLED_DISABLE_OTA diff --git a/wled00/wled.h b/wled00/wled.h index bb647340b..fcbc11978 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -269,7 +269,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; // Global Variable definitions WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION)); -WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // somehow this will not work if using "const char releaseString[] +WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // must include the quotes when defining, e.g -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\" #define WLED_CODENAME "Kōsen" // AP and OTA default passwords (for maximum security change them!) From d87c5035dd0ac1c908c6a4680640999ab52bbddd Mon Sep 17 00:00:00 2001 From: AlDIY <87589371+dosipod@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:33:22 +0300 Subject: [PATCH 40/52] Update settings_sec.htm --- wled00/data/settings_sec.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index fa75882c0..7fe0fe62e 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -60,8 +60,8 @@

Backup & Restore

⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.
- Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.
- For security reasons, passwords are not backed up. + Incorrect upload or configuration may require a factory reset or re-flashing of your ESP.
+ For security reasons, passwords are not backed up. Backup presets
Restore presets


Backup configuration
@@ -78,4 +78,4 @@ - \ No newline at end of file + From cd1c13b4b1e242e736cad086abcb7a9dcc727b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Tue, 26 Nov 2024 19:35:15 +0100 Subject: [PATCH 41/52] Fix for #4300 --- wled00/set.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/set.cpp b/wled00/set.cpp index 712e5f254..2a6fdd3fb 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -215,6 +215,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed // we will not bother with pre-allocating ColorOrderMappings vector + BusManager::getColorOrderMap().reset(); for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { int offset = s < 10 ? 48 : 55; char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED From 1a8aaa3b26feba106259b6842ad9f8998fb3233d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 26 Nov 2024 20:32:39 +0100 Subject: [PATCH 42/52] Speed improvements, commented legacy _t trig functions - speed improvement: by default M_TWOPI is treated as a double float - directly calling sin16_t in cos_approx() saves a lot of overhead --- wled00/wled_math.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index a191968e1..583381d66 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -10,14 +10,17 @@ //#define WLED_DEBUG_MATH -#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) - -// Note: cos_t, sin_t and tan_t are very accurate but may be slow +// Note: cos_t, sin_t and tan_t are very accurate but slow // the math.h functions use several kB of flash and are to be avoided if possible // sin16_t / cos16_t are faster and much more accurate than the fastled variants // sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate + +// Taylor series approximations, replaced with Bhaskara I's approximation +/* +#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) + float cos_t(float phi) { float x = modd(phi, M_TWOPI); @@ -54,6 +57,7 @@ float tan_t(float x) { #endif return res; } +*/ // 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) // input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) @@ -85,17 +89,18 @@ uint8_t cos8_t(uint8_t theta) { return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) } -float sin_approx(float theta) -{ - uint16_t scaled_theta = (int)(theta * (0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) +float sin_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; } -float cos_approx(float theta) -{ - return sin_approx(theta + M_PI_2); +float cos_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) + int32_t result = sin16_t(scaled_theta + 16384); + float cos = float(result) / 0x7FFF; + return cos; } float tan_approx(float x) { From ca176c7549f92ae6ba611b9b6f9e9edbf13bad15 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:31:41 +0000 Subject: [PATCH 43/52] rename workflow ready for workflow refactor --- .github/workflows/{wled-ci.yml => build.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{wled-ci.yml => build.yml} (100%) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/build.yml similarity index 100% rename from .github/workflows/wled-ci.yml rename to .github/workflows/build.yml From feab27295db32f9ad367ec3a68d3d7ad9b3779eb Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:33:44 +0000 Subject: [PATCH 44/52] workflow refactor to used shared build file --- .github/workflows/build.yml | 8 +++++--- .github/workflows/wled-ci.yml | 11 +++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/wled-ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1dcab26ab..80fce38c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,9 @@ -name: WLED CI - -on: [push, pull_request] +name: WLED Build +# Only included into other workflows +on: + workflow_call: + jobs: get_default_envs: diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml new file mode 100644 index 000000000..3c862c185 --- /dev/null +++ b/.github/workflows/wled-ci.yml @@ -0,0 +1,11 @@ +name: WLED CI + +on: + push: + branches: + - '*' + pull_request: + +jobs: + wled_build: + uses: ./.github/workflows/build.yml From 95718ab6ecb830b57f74d7cbed0b142d70b33c63 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:35:04 +0000 Subject: [PATCH 45/52] Dedicated release workflow --- .github/workflows/build.yml | 16 ---------------- .github/workflows/release.yml | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80fce38c3..e5fdfc5a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,22 +64,6 @@ jobs: path: | build_output/release/*.bin build_output/release/*_ESP02*.bin.gz - release: - name: Create Release - runs-on: ubuntu-latest - needs: build - if: startsWith(github.ref, 'refs/tags/') - steps: - - uses: actions/download-artifact@v4 - with: - merge-multiple: true - - name: Create draft release - uses: softprops/action-gh-release@v1 - with: - draft: True - files: | - *.bin - *.bin.gz testCdata: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..27beec99c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: WLED Release CI + +on: + push: + tags: + - '*' + +jobs: + + wled_build: + uses: ./.github/workflows/build.yml + + release: + name: Create Release + runs-on: ubuntu-latest + needs: wled_build + steps: + - uses: actions/download-artifact@v4 + with: + merge-multiple: true + - name: Create draft release + uses: softprops/action-gh-release@v1 + with: + draft: True + files: | + *.bin + *.bin.gz + From cc55f6015dfff436cb4ff3f595ae53695393f8b3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:56:53 +0000 Subject: [PATCH 46/52] Cache always misses for tags, so save space and do not save back --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5fdfc5a3..ac1db6445 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,6 +42,7 @@ jobs: - run: npm ci - name: Cache PlatformIO uses: actions/cache@v4 + if: !startsWith(github.ref, 'refs/tags/') with: path: | ~/.platformio/.cache From 6cbdd825eb6cea9c2cc5c6219f4fd7db567cd8ff Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 27 Nov 2024 10:59:23 +0000 Subject: [PATCH 47/52] Revert "Cache always misses for tags, so save space and do not save back" This reverts commit cc55f6015dfff436cb4ff3f595ae53695393f8b3. --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac1db6445..e5fdfc5a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,6 @@ jobs: - run: npm ci - name: Cache PlatformIO uses: actions/cache@v4 - if: !startsWith(github.ref, 'refs/tags/') with: path: | ~/.platformio/.cache From acc8b9cdbc22086762d5c05e6d2ff419c96fc074 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 27 Nov 2024 09:00:25 -0500 Subject: [PATCH 48/52] BusDigital::begin: Pass clock rate argument Fixes bug introduced by #4312. --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 8281211c1..715470800 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -412,7 +412,7 @@ std::vector BusDigital::getLEDTypes() { void BusDigital::begin() { if (!_valid) return; - PolyBus::begin(_busPtr, _iType, _pins); + PolyBus::begin(_busPtr, _iType, _pins, _frequencykHz); } void BusDigital::cleanup() { From dcba1aad109c29b9594973d99270f62006dd0289 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 27 Nov 2024 09:05:10 -0500 Subject: [PATCH 49/52] PolyBus: Clarify use of clock_kHz While not used by most bus types, it's not an optional parameter. --- wled00/bus_manager.cpp | 2 +- wled00/bus_wrapper.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 715470800..5b031bebb 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -150,7 +150,7 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) //_buffering = bc.doubleBuffer; uint16_t lenToCreate = bc.count; if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus - _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz); + _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr); _valid = (_busPtr != nullptr); DEBUG_PRINTF_P(PSTR("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n"), _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], is2Pin(bc.type)?_pins[1]:255, _iType, _milliAmpsPerLed, _milliAmpsMax); } diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 7e6e74d85..d2a18c9d8 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -336,7 +336,7 @@ class PolyBus { // initialize SPI bus speed for DotStar methods template - static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz = 0U) { + static void beginDotStar(void* busPtr, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint16_t clock_kHz /* 0 == use default */) { T dotStar_strip = static_cast(busPtr); #ifdef ESP8266 dotStar_strip->Begin(); @@ -363,7 +363,7 @@ class PolyBus { tm1914_strip->SetPixelSettings(NeoTm1914Settings()); //NeoTm1914_Mode_DinFdinAutoSwitch, NeoTm1914_Mode_DinOnly, NeoTm1914_Mode_FdinOnly } - static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz = 0U) { + static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz /* only used by DotStar */) { switch (busType) { case I_NONE: break; #ifdef ESP8266 @@ -480,7 +480,7 @@ class PolyBus { } } - static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) { + static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel) { #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation // since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation From b1dd27b516fa93919edd967c85bd8b287b9b914d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Wed, 27 Nov 2024 16:08:10 +0100 Subject: [PATCH 50/52] Fix for #4321 --- wled00/data/settings_leds.htm | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6be5becd1..baf80a5d7 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -42,15 +42,14 @@ if (loc) d.Sf.action = getURL('/settings/leds'); } function bLimits(b,v,p,m,l,o=5,d=2,a=6) { - // maxB - max buses (can be changed if using ESP32 parallel I2S) - // maxD - max digital channels (can be changed if using ESP32 parallel I2S) - // maxA - max analog channels - // maxV - min virtual buses - // maxPB - max LEDs per bus - // maxM - max LED memory - // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) - // maxCO - max Color Order mappings - oMaxB = maxB = b; maxD = d, maxA = a, maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o; + oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S) + maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S) + maxA = a; // maxA - max analog channels + maxV = v; // maxV - min virtual buses + maxPB = p; // maxPB - max LEDs per bus + maxM = m; // maxM - max LED memory + maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) + maxCO = o; // maxCO - max Color Order mappings } function pinsOK() { var ok = true; From 4cd0563a9398812f65f8dbbe22d0ab48799f4de8 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 27 Nov 2024 21:53:32 +0100 Subject: [PATCH 51/52] =?UTF-8?q?changed=2090=C2=B0=20offset=20to=20hex,?= =?UTF-8?q?=20fixed=20potential=20bug=20in=20FX=20using=20sin/cos=20with?= =?UTF-8?q?=20incrementing=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sin/cos calls with incrementing numbers can lead to bad outcomes, the functions (_approx or original sinf/cosf) return bad values for very large float inputs --- wled00/FX.cpp | 5 +++-- wled00/wled_math.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5b4513dc7..da2967a3c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5314,8 +5314,8 @@ uint16_t mode_2DJulia(void) { // An animated Julia set reAl = -0.94299f; // PixelBlaze example imAg = 0.3162f; - reAl += sin_t((float)strip.now/305.f)/20.f; - imAg += sin_t((float)strip.now/405.f)/20.f; + reAl += (float)sin16_t(strip.now * 34) / 655340.f; + imAg += (float)sin16_t(strip.now * 26) / 655340.f; dx = (xmax - xmin) / (cols); // Scale the delta x and y values to our matrix size. dy = (ymax - ymin) / (rows); @@ -6279,6 +6279,7 @@ uint16_t mode_2Dplasmarotozoom() { } } *a -= 0.03f + float(SEGENV.speed-128)*0.0002f; // rotation speed + if(*a < -6283.18530718f) *a += 6283.18530718f; // 1000*2*PI, protect sin/cos from very large input float values (will give wrong results) return FRAMETIME; } diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index 583381d66..a8ec55400 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -76,7 +76,7 @@ int16_t sin16_t(uint16_t theta) { } int16_t cos16_t(uint16_t theta) { - return sin16_t(theta + 16384); //cos(x) = sin(x+pi/2) + return sin16_t(theta + 0x4000); //cos(x) = sin(x+pi/2) } uint8_t sin8_t(uint8_t theta) { @@ -98,7 +98,7 @@ float sin_approx(float theta) { float cos_approx(float theta) { uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) - int32_t result = sin16_t(scaled_theta + 16384); + int32_t result = sin16_t(scaled_theta + 0x4000); float cos = float(result) / 0x7FFF; return cos; } From fa4c23b76ec7843aff6a8f3e5b9bc7a46a41858e Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 27 Nov 2024 22:23:48 +0100 Subject: [PATCH 52/52] minor improvement --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a2ceb591a..a0d080818 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7737,9 +7737,9 @@ uint16_t mode_2Doctopus() { const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255; for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - rMap[XY(x, y)].angle = int(40.7436f * atan2_t((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI int dx = (x - C_X); int dy = (y - C_Y); + rMap[XY(x, y)].angle = int(40.7436f * atan2_t(dy, dx)); // avoid 128*atan2()/PI rMap[XY(x, y)].radius = sqrtf(dx * dx + dy * dy) * mapp; //thanks Sutaburosu } }