Multiple updates:
- additional debug timings - removed local leds[] buffer - async segment bounds change (crashes seen otherwise) - added isActive() check to Segment drawing methods - ABL simplification - palette option for Black hole (FX) - (possible) crash mitigation is Segment handling (rapid preset changes)
This commit is contained in:
parent
6267d11e51
commit
fa6070c680
@ -606,7 +606,6 @@ static const char _data_FX_MODE_TWINKLE[] PROGMEM = "Twinkle@!,!;!,!;!;;m12=0";
|
|||||||
uint16_t dissolve(uint32_t color) {
|
uint16_t dissolve(uint32_t color) {
|
||||||
//bool wa = (SEGCOLOR(1) != 0 && strip.getBrightness() < 255); //workaround, can't compare getPixel to color if not full brightness
|
//bool wa = (SEGCOLOR(1) != 0 && strip.getBrightness() < 255); //workaround, can't compare getPixel to color if not full brightness
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds(); //lossless getPixelColor()
|
|
||||||
SEGMENT.fill(SEGCOLOR(1));
|
SEGMENT.fill(SEGCOLOR(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1205,7 +1204,6 @@ uint16_t mode_fireworks() {
|
|||||||
const uint16_t height = SEGMENT.virtualHeight();
|
const uint16_t height = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds(); //lossless getPixelColor()
|
|
||||||
SEGMENT.fill(SEGCOLOR(1));
|
SEGMENT.fill(SEGCOLOR(1));
|
||||||
SEGENV.aux0 = UINT16_MAX;
|
SEGENV.aux0 = UINT16_MAX;
|
||||||
SEGENV.aux1 = UINT16_MAX;
|
SEGENV.aux1 = UINT16_MAX;
|
||||||
@ -1904,7 +1902,6 @@ static const char _data_FX_MODE_PRIDE_2015[] PROGMEM = "Pride 2015@!;;";
|
|||||||
uint16_t mode_juggle(void) {
|
uint16_t mode_juggle(void) {
|
||||||
if (SEGLEN == 1) return mode_static();
|
if (SEGLEN == 1) return mode_static();
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds(); //lossless getPixelColor()
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4585,7 +4582,6 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
|
|||||||
|
|
||||||
// initialize on first call
|
// initialize on first call
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4595,22 +4591,22 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
|
|||||||
for (size_t i = 0; i < 8; i++) {
|
for (size_t i = 0; i < 8; i++) {
|
||||||
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * 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);
|
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(i*32, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255));
|
||||||
}
|
}
|
||||||
// inner stars
|
// inner stars
|
||||||
for (size_t i = 0; i < 4; i++) {
|
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);
|
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);
|
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
SEGMENT.addPixelColorXY(x, y, SEGMENT.color_from_palette(255-i*64, false, PALETTE_SOLID_WRAP, SEGMENT.check1?0:255));
|
||||||
}
|
}
|
||||||
// central white dot
|
// central white dot
|
||||||
SEGMENT.setPixelColorXY(cols/2, rows/2, CHSV(0, 0, 255));
|
SEGMENT.setPixelColorXY(cols/2, rows/2, WHITE);
|
||||||
// blur everything a bit
|
// blur everything a bit
|
||||||
SEGMENT.blur(16);
|
SEGMENT.blur(16);
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
} // mode_2DBlackHole()
|
} // mode_2DBlackHole()
|
||||||
static const char _data_FX_MODE_2DBLACKHOLE[] PROGMEM = "Black Hole@Fade rate,Outer Y freq.,Outer X freq.,Inner X freq.,Inner Y freq.;;;2";
|
static const char _data_FX_MODE_2DBLACKHOLE[] PROGMEM = "Black Hole@Fade rate,Outer Y freq.,Outer X freq.,Inner X freq.,Inner Y freq.,Solid;!;!;2;pal=11";
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@ -4623,7 +4619,6 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
SEGENV.aux0 = 0; // start with red hue
|
SEGENV.aux0 = 0; // start with red hue
|
||||||
}
|
}
|
||||||
@ -4677,7 +4672,6 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4704,7 +4698,6 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4750,7 +4743,6 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4781,7 +4773,6 @@ uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4816,7 +4807,6 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4855,8 +4845,6 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
|
|||||||
|
|
||||||
CRGB backgroundColor = SEGCOLOR(1);
|
CRGB backgroundColor = SEGCOLOR(1);
|
||||||
|
|
||||||
if (SEGENV.call == 0) SEGMENT.setUpLeds();
|
|
||||||
|
|
||||||
if (SEGENV.call == 0 || strip.now - SEGMENT.step > 3000) {
|
if (SEGENV.call == 0 || strip.now - SEGMENT.step > 3000) {
|
||||||
SEGENV.step = strip.now;
|
SEGENV.step = strip.now;
|
||||||
SEGENV.aux0 = 0;
|
SEGENV.aux0 = 0;
|
||||||
@ -5122,7 +5110,6 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5267,7 +5254,6 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5315,7 +5301,6 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https
|
|||||||
CRGBPalette16 auroraPalette = {0x000000, 0x003300, 0x006600, 0x009900, 0x00cc00, 0x00ff00, 0x33ff00, 0x66ff00, 0x99ff00, 0xccff00, 0xffff00, 0xffcc00, 0xff9900, 0xff6600, 0xff3300, 0xff0000};
|
CRGBPalette16 auroraPalette = {0x000000, 0x003300, 0x006600, 0x009900, 0x00cc00, 0x00ff00, 0x33ff00, 0x66ff00, 0x99ff00, 0xccff00, 0xffff00, 0xffcc00, 0xff9900, 0xff6600, 0xff3300, 0xff0000};
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
SEGENV.step = 0;
|
SEGENV.step = 0;
|
||||||
}
|
}
|
||||||
@ -5365,7 +5350,6 @@ uint16_t mode_2DPulser(void) { // By: ldirko https://edi
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5393,7 +5377,6 @@ uint16_t mode_2DSindots(void) { // By: ldirko http
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5425,7 +5408,6 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5468,7 +5450,6 @@ uint16_t mode_2DSunradiation(void) { // By: ldirko https://edi
|
|||||||
byte *bump = reinterpret_cast<byte*>(SEGENV.data);
|
byte *bump = reinterpret_cast<byte*>(SEGENV.data);
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5516,7 +5497,6 @@ uint16_t mode_2Dtartan(void) { // By: Elliott Kember https://editor.so
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5556,7 +5536,6 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5625,7 +5604,6 @@ uint16_t mode_2Dcrazybees(void) {
|
|||||||
bee_t *bee = reinterpret_cast<bee_t*>(SEGENV.data);
|
bee_t *bee = reinterpret_cast<bee_t*>(SEGENV.data);
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
bee[i].posX = random8(0, cols);
|
bee[i].posX = random8(0, cols);
|
||||||
@ -5695,7 +5673,6 @@ uint16_t mode_2Dghostrider(void) {
|
|||||||
|
|
||||||
const size_t maxLighters = min(cols + rows, LIGHTERS_AM);
|
const size_t maxLighters = min(cols + rows, LIGHTERS_AM);
|
||||||
|
|
||||||
if (SEGENV.call == 0) SEGMENT.setUpLeds();
|
|
||||||
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
||||||
SEGENV.aux0 = cols;
|
SEGENV.aux0 = cols;
|
||||||
SEGENV.aux1 = rows;
|
SEGENV.aux1 = rows;
|
||||||
@ -5780,7 +5757,6 @@ uint16_t mode_2Dfloatingblobs(void) {
|
|||||||
if (!SEGENV.allocateData(sizeof(blob_t))) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(sizeof(blob_t))) return mode_static(); //allocation failed
|
||||||
blob_t *blob = reinterpret_cast<blob_t*>(SEGENV.data);
|
blob_t *blob = reinterpret_cast<blob_t*>(SEGENV.data);
|
||||||
|
|
||||||
if (SEGENV.call == 0) SEGMENT.setUpLeds();
|
|
||||||
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
||||||
SEGENV.aux0 = cols; // re-initialise if virtual size changes
|
SEGENV.aux0 = cols; // re-initialise if virtual size changes
|
||||||
SEGENV.aux1 = rows;
|
SEGENV.aux1 = rows;
|
||||||
@ -5946,7 +5922,6 @@ uint16_t mode_2Ddriftrose(void) {
|
|||||||
const float L = min(cols, rows) / 2.f;
|
const float L = min(cols, rows) / 2.f;
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6101,7 +6076,6 @@ uint16_t mode_2DSwirl(void) {
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6148,7 +6122,6 @@ uint16_t mode_2DWaverly(void) {
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6377,7 +6350,6 @@ uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline.
|
|||||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6505,7 +6477,6 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline.
|
|||||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6731,7 +6702,6 @@ uint16_t mode_DJLight(void) { // Written by ??? Adapted by Wil
|
|||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6800,7 +6770,6 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
|||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6902,7 +6871,6 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
|||||||
float volumeSmth = *(float*)um_data->u_data[0];
|
float volumeSmth = *(float*)um_data->u_data[0];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7087,7 +7055,6 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
|
|||||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
SEGENV.aux0 = 255;
|
SEGENV.aux0 = 255;
|
||||||
SEGMENT.custom1 = *binNum;
|
SEGMENT.custom1 = *binNum;
|
||||||
@ -7204,7 +7171,6 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil
|
|||||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||||
|
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7417,7 +7383,6 @@ uint16_t mode_2Dsoap() {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
if (SEGENV.call == 0) {
|
if (SEGENV.call == 0) {
|
||||||
SEGMENT.setUpLeds();
|
|
||||||
*noise32_x = random16();
|
*noise32_x = random16();
|
||||||
*noise32_y = random16();
|
*noise32_y = random16();
|
||||||
*noise32_z = random16();
|
*noise32_z = random16();
|
||||||
@ -7535,12 +7500,12 @@ uint16_t mode_2Doctopus() {
|
|||||||
SEGENV.aux1 = rows;
|
SEGENV.aux1 = rows;
|
||||||
*offsX = SEGMENT.custom1;
|
*offsX = SEGMENT.custom1;
|
||||||
*offsY = SEGMENT.custom2;
|
*offsY = SEGMENT.custom2;
|
||||||
const uint8_t C_X = cols / 2 + (SEGMENT.custom1 - 128)*cols/255;
|
const int C_X = (cols / 2) + ((SEGMENT.custom1 - 128)*cols)/255;
|
||||||
const uint8_t C_Y = rows / 2 + (SEGMENT.custom2 - 128)*rows/255;
|
const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255;
|
||||||
for (int x = 0; x < cols; x++) {
|
for (int x = 0; x < cols; x++) {
|
||||||
for (int y = 0; y < rows; y++) {
|
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 * atan2f((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)].radius = hypotf((x - C_X), (y - C_Y)) * mapp; //thanks Sutaburosu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
36
wled00/FX.h
36
wled00/FX.h
@ -329,7 +329,7 @@ typedef enum mapping1D2D {
|
|||||||
M12_pCorner = 3
|
M12_pCorner = 3
|
||||||
} mapping1D2D_t;
|
} mapping1D2D_t;
|
||||||
|
|
||||||
// segment, 72 bytes
|
// segment, 80 bytes
|
||||||
typedef struct Segment {
|
typedef struct Segment {
|
||||||
public:
|
public:
|
||||||
uint16_t start; // start index / start X coordinate 2D (left)
|
uint16_t start; // start index / start X coordinate 2D (left)
|
||||||
@ -370,7 +370,7 @@ typedef struct Segment {
|
|||||||
};
|
};
|
||||||
uint8_t startY; // start Y coodrinate 2D (top); there should be no more than 255 rows
|
uint8_t startY; // start Y coodrinate 2D (top); there should be no more than 255 rows
|
||||||
uint8_t stopY; // stop Y coordinate 2D (bottom); there should be no more than 255 rows
|
uint8_t stopY; // stop Y coordinate 2D (bottom); there should be no more than 255 rows
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
// runtime data
|
// runtime data
|
||||||
unsigned long next_time; // millis() of next update
|
unsigned long next_time; // millis() of next update
|
||||||
@ -378,8 +378,7 @@ typedef struct Segment {
|
|||||||
uint32_t call; // call counter
|
uint32_t call; // call counter
|
||||||
uint16_t aux0; // custom var
|
uint16_t aux0; // custom var
|
||||||
uint16_t aux1; // custom var
|
uint16_t aux1; // custom var
|
||||||
byte* data; // effect data pointer
|
byte *data; // effect data pointer
|
||||||
uint32_t* leds; // local leds[] array (may be a pointer to global)
|
|
||||||
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -393,10 +392,13 @@ typedef struct Segment {
|
|||||||
uint8_t _reserved : 4;
|
uint8_t _reserved : 4;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
uint16_t _dataLen;
|
uint16_t _dataLen;
|
||||||
static uint16_t _usedSegmentData;
|
static uint16_t _usedSegmentData;
|
||||||
|
|
||||||
// transition data, valid only if transitional==true, holds values during transition
|
uint16_t _qStart, _qStop, _qStartY, _qStopY;
|
||||||
|
bool _queuedChanges;
|
||||||
|
|
||||||
|
// transition data, valid only if transitional==true, holds values during transition (72 bytes)
|
||||||
struct Transition {
|
struct Transition {
|
||||||
uint32_t _colorT[NUM_COLORS];
|
uint32_t _colorT[NUM_COLORS];
|
||||||
uint8_t _briT; // temporary brightness
|
uint8_t _briT; // temporary brightness
|
||||||
@ -407,7 +409,7 @@ typedef struct Segment {
|
|||||||
//uint16_t _aux0, _aux1; // previous mode/effect runtime data
|
//uint16_t _aux0, _aux1; // previous mode/effect runtime data
|
||||||
//uint32_t _step, _call; // previous mode/effect runtime data
|
//uint32_t _step, _call; // previous mode/effect runtime data
|
||||||
//byte *_data; // previous mode/effect runtime data
|
//byte *_data; // previous mode/effect runtime data
|
||||||
uint32_t _start;
|
unsigned long _start; // must accommodate millis()
|
||||||
uint16_t _dur;
|
uint16_t _dur;
|
||||||
Transition(uint16_t dur=750)
|
Transition(uint16_t dur=750)
|
||||||
: _briT(255)
|
: _briT(255)
|
||||||
@ -462,9 +464,9 @@ typedef struct Segment {
|
|||||||
aux0(0),
|
aux0(0),
|
||||||
aux1(0),
|
aux1(0),
|
||||||
data(nullptr),
|
data(nullptr),
|
||||||
leds(nullptr),
|
|
||||||
_capabilities(0),
|
_capabilities(0),
|
||||||
_dataLen(0),
|
_dataLen(0),
|
||||||
|
_queuedChanges(false),
|
||||||
_t(nullptr)
|
_t(nullptr)
|
||||||
{
|
{
|
||||||
//refreshLightCapabilities();
|
//refreshLightCapabilities();
|
||||||
@ -485,9 +487,8 @@ typedef struct Segment {
|
|||||||
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
||||||
//Serial.println();
|
//Serial.println();
|
||||||
//#endif
|
//#endif
|
||||||
if (name) delete[] name;
|
if (name) { delete[] name; name = nullptr; }
|
||||||
if (_t) delete _t;
|
if (_t) { transitional = false; delete _t; _t = nullptr; }
|
||||||
if (leds) free(leds);
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +496,7 @@ typedef struct Segment {
|
|||||||
Segment& operator= (Segment &&orig) noexcept; // move assignment
|
Segment& operator= (Segment &&orig) noexcept; // move assignment
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (leds?sizeof(CRGB)*length():0); }
|
size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
|
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
|
||||||
@ -505,16 +506,16 @@ typedef struct Segment {
|
|||||||
inline bool hasRGB(void) const { return _isRGB; }
|
inline bool hasRGB(void) const { return _isRGB; }
|
||||||
inline bool hasWhite(void) const { return _hasW; }
|
inline bool hasWhite(void) const { return _hasW; }
|
||||||
inline bool isCCT(void) const { return _isCCT; }
|
inline bool isCCT(void) const { return _isCCT; }
|
||||||
inline uint16_t width(void) const { return (stop > start) ? (stop - start) : 0; } // segment width in physical pixels (length if 1D)
|
inline uint16_t width(void) const { return isActive() ? (stop - start) : 0; } // segment width in physical pixels (length if 1D)
|
||||||
inline uint16_t height(void) const { return (stopY > startY) ? (stopY - startY) : 0; } // segment height (if 2D) in physical pixels // softhack007: make sure its always > 0
|
inline uint16_t height(void) const { return stopY - startY; } // segment height (if 2D) in physical pixels (it *is* always >=1)
|
||||||
inline uint16_t length(void) const { return width() * height(); } // segment length (count) in physical pixels
|
inline uint16_t length(void) const { return width() * height(); } // segment length (count) in physical pixels
|
||||||
inline uint16_t groupLength(void) const { return grouping + spacing; }
|
inline uint16_t groupLength(void) const { return grouping + spacing; }
|
||||||
inline uint8_t getLightCapabilities(void) const { return _capabilities; }
|
inline uint8_t getLightCapabilities(void) const { return _capabilities; }
|
||||||
|
|
||||||
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
||||||
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
||||||
|
|
||||||
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1);
|
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, bool immediate=false);
|
||||||
bool setColor(uint8_t slot, uint32_t c); //returns true if changed
|
bool setColor(uint8_t slot, uint32_t c); //returns true if changed
|
||||||
void setCCT(uint16_t k);
|
void setCCT(uint16_t k);
|
||||||
void setOpacity(uint8_t o);
|
void setOpacity(uint8_t o);
|
||||||
@ -536,7 +537,6 @@ typedef struct Segment {
|
|||||||
* Safe to call from interrupts and network requests.
|
* Safe to call from interrupts and network requests.
|
||||||
*/
|
*/
|
||||||
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
|
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
|
||||||
void setUpLeds(void); // local double buffer/lossless getPixelColor()
|
|
||||||
|
|
||||||
// transition functions
|
// transition functions
|
||||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||||
@ -896,7 +896,7 @@ class WS2812FX { // 96 bytes
|
|||||||
uint16_t* customMappingTable;
|
uint16_t* customMappingTable;
|
||||||
uint16_t customMappingSize;
|
uint16_t customMappingSize;
|
||||||
|
|
||||||
uint32_t _lastShow;
|
unsigned long _lastShow;
|
||||||
|
|
||||||
uint8_t _segment_index;
|
uint8_t _segment_index;
|
||||||
uint8_t _mainSegment;
|
uint8_t _mainSegment;
|
||||||
|
@ -189,20 +189,16 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
|||||||
|
|
||||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||||
uint16_t /*IRAM_ATTR*/ Segment::XY(uint16_t x, uint16_t y) {
|
uint16_t /*IRAM_ATTR*/ Segment::XY(uint16_t x, uint16_t y) {
|
||||||
uint16_t width = virtualWidth(); // segment width in logical pixels
|
uint16_t width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
|
||||||
uint16_t height = virtualHeight(); // segment height in logical pixels
|
uint16_t height = virtualHeight(); // segment height in logical pixels (is always >= 1)
|
||||||
if (width == 0) return 0; // softhack007 avoid div/0
|
return isActive() ? (x%width) + (y%height) * width : 0;
|
||||||
if (height == 0) return (x%width); // softhack007 avoid div/0
|
|
||||||
return (x%width) + (y%height) * width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||||
{
|
{
|
||||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
if (!isActive()) return; // not active
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||||
|
|
||||||
if (leds) leds[XY(x,y)] = col;
|
|
||||||
|
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
@ -245,7 +241,7 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
// anti-aliased version of setPixelColorXY()
|
// anti-aliased version of setPixelColorXY()
|
||||||
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
||||||
{
|
{
|
||||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
if (!isActive()) return; // not active
|
||||||
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||||
|
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
@ -288,7 +284,8 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
|||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||||
if (leds) return leds[XY(x,y)];
|
if (!isActive()) return 0; // not active
|
||||||
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
|
||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
if (reverse_y) y = virtualHeight() - y - 1;
|
if (reverse_y) y = virtualHeight() - y - 1;
|
||||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
@ -305,6 +302,7 @@ void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t
|
|||||||
|
|
||||||
// Adds the specified color with the existing pixel color perserving color balance.
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||||
uint32_t col = getPixelColorXY(x,y);
|
uint32_t col = getPixelColorXY(x,y);
|
||||||
uint8_t r = R(col);
|
uint8_t r = R(col);
|
||||||
@ -324,12 +322,14 @@ void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
|
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
|
||||||
setPixelColorXY(x, y, pix);
|
setPixelColorXY(x, y, pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@ -357,6 +357,7 @@ void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
|||||||
|
|
||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@ -384,6 +385,7 @@ void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
|||||||
|
|
||||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||||
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
const uint16_t dim1 = vertical ? rows : cols;
|
const uint16_t dim1 = vertical ? rows : cols;
|
||||||
@ -436,6 +438,7 @@ void Segment::blur1d(fract8 blur_amount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::moveX(int8_t delta, bool wrap) {
|
void Segment::moveX(int8_t delta, bool wrap) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
if (!delta || abs(delta) >= cols) return;
|
if (!delta || abs(delta) >= cols) return;
|
||||||
@ -453,6 +456,7 @@ void Segment::moveX(int8_t delta, bool wrap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::moveY(int8_t delta, bool wrap) {
|
void Segment::moveY(int8_t delta, bool wrap) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
if (!delta || abs(delta) >= rows) return;
|
if (!delta || abs(delta) >= rows) return;
|
||||||
@ -488,6 +492,7 @@ void Segment::move(uint8_t dir, uint8_t delta, bool wrap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
// Bresenham’s Algorithm
|
// Bresenham’s Algorithm
|
||||||
int d = 3 - (2*radius);
|
int d = 3 - (2*radius);
|
||||||
int y = radius, x = 0;
|
int y = radius, x = 0;
|
||||||
@ -512,6 +517,7 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
|
|
||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
for (int16_t y = -radius; y <= radius; y++) {
|
for (int16_t y = -radius; y <= radius; y++) {
|
||||||
@ -525,6 +531,7 @@ void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::nscale8(uint8_t scale) {
|
void Segment::nscale8(uint8_t scale) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
@ -534,6 +541,7 @@ void Segment::nscale8(uint8_t scale) {
|
|||||||
|
|
||||||
//line function
|
//line function
|
||||||
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
|
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||||
@ -558,6 +566,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
// draws a raster font character on canvas
|
// draws a raster font character on canvas
|
||||||
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
||||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
|
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
||||||
chr -= 32; // align with font table entries
|
chr -= 32; // align with font table entries
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
@ -593,6 +602,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
|
|
||||||
#define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))
|
#define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))
|
||||||
void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
||||||
|
if (!isActive()) return; // not active
|
||||||
// extract the fractional parts and derive their inverses
|
// extract the fractional parts and derive their inverses
|
||||||
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
||||||
// calculate the intensities for each affected pixel
|
// calculate the intensities for each affected pixel
|
||||||
|
@ -81,22 +81,21 @@ uint16_t Segment::maxHeight = 1;
|
|||||||
Segment::Segment(const Segment &orig) {
|
Segment::Segment(const Segment &orig) {
|
||||||
//DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
//DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
|
transitional = false; // copied segment cannot be in transition
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
_t = nullptr;
|
_t = nullptr;
|
||||||
leds = nullptr;
|
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||||
if (orig.leds) { leds = (uint32_t*)malloc(sizeof(uint32_t)*length()); if (leds) memcpy(leds, orig.leds, sizeof(uint32_t)*length()); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
Segment::Segment(Segment &&orig) noexcept {
|
Segment::Segment(Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
//DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.leds = nullptr;
|
orig.transitional = false; // old segment cannot be in transition any more
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
@ -108,23 +107,22 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
//DEBUG_PRINTLN(F("-- Copying segment --"));
|
//DEBUG_PRINTLN(F("-- Copying segment --"));
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
// clean destination
|
// clean destination
|
||||||
|
transitional = false; // copied segment cannot be in transition
|
||||||
if (name) delete[] name;
|
if (name) delete[] name;
|
||||||
if (_t) delete _t;
|
if (_t) delete _t;
|
||||||
if (leds) free(leds);
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
// copy source
|
// copy source
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
|
transitional = false;
|
||||||
// erase pointers to allocated data
|
// erase pointers to allocated data
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
_t = nullptr;
|
_t = nullptr;
|
||||||
leds = nullptr;
|
|
||||||
// copy source data
|
// copy source data
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||||
if (orig.leds) { leds = (uint32_t*)malloc(sizeof(uint32_t)*length()); if (leds) memcpy(leds, orig.leds, sizeof(uint32_t)*length()); }
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -133,16 +131,16 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
Segment& Segment::operator= (Segment &&orig) noexcept {
|
Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTLN(F("-- Moving segment --"));
|
//DEBUG_PRINTLN(F("-- Moving segment --"));
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
if (name) delete[] name; // free old name
|
transitional = false; // just temporary
|
||||||
if (leds) free(leds);
|
if (name) { delete[] name; name = nullptr; } // free old name
|
||||||
deallocateData(); // free old runtime data
|
deallocateData(); // free old runtime data
|
||||||
if (_t) delete _t;
|
if (_t) { delete _t; _t = nullptr; }
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
|
orig.transitional = false; // old segment cannot be in transition
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
orig._t = nullptr;
|
orig._t = nullptr;
|
||||||
orig.leds = nullptr;
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -152,12 +150,7 @@ bool Segment::allocateData(size_t len) {
|
|||||||
deallocateData();
|
deallocateData();
|
||||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||||
// do not use SPI RAM on ESP32 since it is slow
|
// do not use SPI RAM on ESP32 since it is slow
|
||||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
data = (byte*) malloc(len);
|
||||||
//if (psramFound())
|
|
||||||
// data = (byte*) ps_malloc(len);
|
|
||||||
//else
|
|
||||||
//#endif
|
|
||||||
data = (byte*) malloc(len);
|
|
||||||
if (!data) return false; //allocation failed
|
if (!data) return false; //allocation failed
|
||||||
Segment::addUsedSegmentData(len);
|
Segment::addUsedSegmentData(len);
|
||||||
_dataLen = len;
|
_dataLen = len;
|
||||||
@ -182,28 +175,13 @@ void Segment::deallocateData() {
|
|||||||
*/
|
*/
|
||||||
void Segment::resetIfRequired() {
|
void Segment::resetIfRequired() {
|
||||||
if (reset) {
|
if (reset) {
|
||||||
if (leds) { free(leds); leds = nullptr; }
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
|
if (_queuedChanges) setUp(_qStart, _qStop, grouping, spacing, offset, _qStartY, _qStopY, true);
|
||||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::setUpLeds() {
|
|
||||||
// deallocation happens in resetIfRequired() as it is called when segment changes or in destructor
|
|
||||||
if (useGlobalLedBuffer) return; // TODO optional seg buffer for FX without lossy restore due to opacity
|
|
||||||
|
|
||||||
// no global buffer
|
|
||||||
if (leds == nullptr && length() > 0) { //softhack007 quickfix - avoid malloc(0) which is undefined behaviour (should not happen, but i've seen it)
|
|
||||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
|
||||||
//if (psramFound())
|
|
||||||
// leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards
|
|
||||||
//else
|
|
||||||
//#endif
|
|
||||||
leds = (uint32_t *)calloc(length(), sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||||
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
|
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
|
||||||
static CRGBPalette16 randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
static CRGBPalette16 randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||||
@ -326,7 +304,7 @@ void Segment::startTransition(uint16_t dur) {
|
|||||||
// transition progression between 0-65535
|
// transition progression between 0-65535
|
||||||
uint16_t Segment::progress() {
|
uint16_t Segment::progress() {
|
||||||
if (!transitional || !_t) return 0xFFFFU;
|
if (!transitional || !_t) return 0xFFFFU;
|
||||||
uint32_t timeNow = millis();
|
unsigned long timeNow = millis();
|
||||||
if (timeNow - _t->_start > _t->_dur || _t->_dur == 0) return 0xFFFFU;
|
if (timeNow - _t->_start > _t->_dur || _t->_dur == 0) return 0xFFFFU;
|
||||||
return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||||
}
|
}
|
||||||
@ -355,7 +333,7 @@ CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal
|
|||||||
// blend palettes
|
// blend palettes
|
||||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||||
// minimum blend time is 100ms maximum is 65535ms
|
// minimum blend time is 100ms maximum is 65535ms
|
||||||
uint32_t timeMS = millis() - _t->_start;
|
unsigned long timeMS = millis() - _t->_start;
|
||||||
uint16_t noOfBlends = (255U * timeMS / _t->_dur) - _t->_prevPaletteBlends;
|
uint16_t noOfBlends = (255U * timeMS / _t->_dur) - _t->_prevPaletteBlends;
|
||||||
for (int i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
for (int i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
||||||
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
||||||
@ -376,8 +354,9 @@ void Segment::handleTransition() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y) {
|
void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y, bool immediate) {
|
||||||
//return if neither bounds nor grouping have changed
|
_queuedChanges = false; // cancel anything queued
|
||||||
|
// return if neither bounds nor grouping have changed
|
||||||
bool boundsUnchanged = (start == i1 && stop == i2);
|
bool boundsUnchanged = (start == i1 && stop == i2);
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (Segment::maxHeight>1) boundsUnchanged &= (startY == i1Y && stopY == i2Y); // 2D
|
if (Segment::maxHeight>1) boundsUnchanged &= (startY == i1Y && stopY == i2Y); // 2D
|
||||||
@ -386,29 +365,47 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
|
|||||||
&& (!grp || (grouping == grp && spacing == spc))
|
&& (!grp || (grouping == grp && spacing == spc))
|
||||||
&& (ofs == UINT16_MAX || ofs == offset)) return;
|
&& (ofs == UINT16_MAX || ofs == offset)) return;
|
||||||
|
|
||||||
if (stop) fill(BLACK); //turn old segment range off
|
if (stop) fill(BLACK); // turn old segment range off (clears pixels if changing spacing)
|
||||||
if (i2 <= i1) { //disable segment
|
if (grp) { // prevent assignment of 0
|
||||||
stop = 0;
|
|
||||||
markForReset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i1 < Segment::maxWidth || (i1 >= Segment::maxWidth*Segment::maxHeight && i1 < strip.getLengthTotal())) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
|
|
||||||
stop = i2 > Segment::maxWidth*Segment::maxHeight ? MIN(i2,strip.getLengthTotal()) : (i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2));
|
|
||||||
startY = 0;
|
|
||||||
stopY = 1;
|
|
||||||
#ifndef WLED_DISABLE_2D
|
|
||||||
if (Segment::maxHeight>1) { // 2D
|
|
||||||
if (i1Y < Segment::maxHeight) startY = i1Y;
|
|
||||||
stopY = i2Y > Segment::maxHeight ? Segment::maxHeight : MAX(1,i2Y);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (grp) {
|
|
||||||
grouping = grp;
|
grouping = grp;
|
||||||
spacing = spc;
|
spacing = spc;
|
||||||
|
} else {
|
||||||
|
grouping = 1;
|
||||||
|
spacing = 0;
|
||||||
}
|
}
|
||||||
if (ofs < UINT16_MAX) offset = ofs;
|
if (ofs < UINT16_MAX) offset = ofs;
|
||||||
|
|
||||||
markForReset();
|
markForReset();
|
||||||
if (!boundsUnchanged) refreshLightCapabilities();
|
if (!boundsUnchanged) {
|
||||||
|
if (immediate) {
|
||||||
|
if (i2 <= i1) { //disable segment
|
||||||
|
stop = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i1 < Segment::maxWidth || (i1 >= Segment::maxWidth*Segment::maxHeight && i1 < strip.getLengthTotal())) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
|
||||||
|
stop = i2 > Segment::maxWidth*Segment::maxHeight ? MIN(i2,strip.getLengthTotal()) : (i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2));
|
||||||
|
startY = 0;
|
||||||
|
stopY = 1;
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (Segment::maxHeight>1) { // 2D
|
||||||
|
if (i1Y < Segment::maxHeight) startY = i1Y;
|
||||||
|
stopY = i2Y > Segment::maxHeight ? Segment::maxHeight : MAX(1,i2Y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// safety check
|
||||||
|
if (start >= stop || startY >= stopY) {
|
||||||
|
stop = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!boundsUnchanged) refreshLightCapabilities();
|
||||||
|
} else {
|
||||||
|
_qStart = i1;
|
||||||
|
_qStop = i2;
|
||||||
|
_qStartY = i1Y;
|
||||||
|
_qStopY = i2Y;
|
||||||
|
_queuedChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -455,8 +452,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
// if we have a valid mode & is not reserved
|
// if we have a valid mode & is not reserved
|
||||||
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
||||||
if (fx != mode) {
|
if (fx != mode) {
|
||||||
startTransition(strip.getTransition()); // set effect transitions
|
if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions
|
||||||
//markForReset(); // transition will handle this
|
|
||||||
mode = fx;
|
mode = fx;
|
||||||
|
|
||||||
// load default values from effect string
|
// load default values from effect string
|
||||||
@ -541,8 +537,7 @@ uint16_t Segment::virtualLength() const {
|
|||||||
return vLen;
|
return vLen;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint16_t groupLen = groupLength();
|
uint16_t groupLen = groupLength(); // is always >= 1
|
||||||
if (groupLen < 1) groupLen = 1; // prevent division by zero - better safe than sorry ...
|
|
||||||
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
||||||
if (mirror) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
if (mirror) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vLength;
|
return vLength;
|
||||||
@ -550,6 +545,7 @@ uint16_t Segment::virtualLength() const {
|
|||||||
|
|
||||||
void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||||
{
|
{
|
||||||
|
if (!isActive()) return; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
int vStrip = i>>16; // hack to allow running on virtual strips (2D segment columns/rows)
|
int vStrip = i>>16; // hack to allow running on virtual strips (2D segment columns/rows)
|
||||||
#endif
|
#endif
|
||||||
@ -617,8 +613,6 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (leds) leds[i] = col;
|
|
||||||
|
|
||||||
uint16_t len = length();
|
uint16_t len = length();
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
@ -660,6 +654,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
// anti-aliased normalized version of setPixelColor()
|
// anti-aliased normalized version of setPixelColor()
|
||||||
void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
||||||
{
|
{
|
||||||
|
if (!isActive()) return; // not active
|
||||||
int vStrip = int(i/10.0f); // hack to allow running on virtual strips (2D segment columns/rows)
|
int vStrip = int(i/10.0f); // hack to allow running on virtual strips (2D segment columns/rows)
|
||||||
i -= int(i);
|
i -= int(i);
|
||||||
|
|
||||||
@ -691,6 +686,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
|||||||
|
|
||||||
uint32_t Segment::getPixelColor(int i)
|
uint32_t Segment::getPixelColor(int i)
|
||||||
{
|
{
|
||||||
|
if (!isActive()) return 0; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
int vStrip = i>>16;
|
int vStrip = i>>16;
|
||||||
#endif
|
#endif
|
||||||
@ -718,8 +714,6 @@ uint32_t Segment::getPixelColor(int i)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (leds) return leds[i];
|
|
||||||
|
|
||||||
if (reverse) i = virtualLength() - i - 1;
|
if (reverse) i = virtualLength() - i - 1;
|
||||||
i *= groupLength();
|
i *= groupLength();
|
||||||
i += start;
|
i += start;
|
||||||
@ -760,6 +754,11 @@ void Segment::refreshLightCapabilities() {
|
|||||||
uint16_t segStartIdx = 0xFFFFU;
|
uint16_t segStartIdx = 0xFFFFU;
|
||||||
uint16_t segStopIdx = 0;
|
uint16_t segStopIdx = 0;
|
||||||
|
|
||||||
|
if (!isActive()) {
|
||||||
|
_capabilities = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (start < Segment::maxWidth * Segment::maxHeight) {
|
if (start < Segment::maxWidth * Segment::maxHeight) {
|
||||||
// we are withing 2D matrix (includes 1D segments)
|
// we are withing 2D matrix (includes 1D segments)
|
||||||
for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) {
|
for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) {
|
||||||
@ -804,6 +803,7 @@ void Segment::refreshLightCapabilities() {
|
|||||||
* Fills segment with color
|
* Fills segment with color
|
||||||
*/
|
*/
|
||||||
void Segment::fill(uint32_t c) {
|
void Segment::fill(uint32_t c) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
@ -819,6 +819,7 @@ void Segment::blendPixelColor(int n, uint32_t color, uint8_t blend) {
|
|||||||
|
|
||||||
// Adds the specified color with the existing pixel color perserving color balance.
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
void Segment::addPixelColor(int n, uint32_t color, bool fast) {
|
void Segment::addPixelColor(int n, uint32_t color, bool fast) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
uint32_t col = getPixelColor(n);
|
uint32_t col = getPixelColor(n);
|
||||||
uint8_t r = R(col);
|
uint8_t r = R(col);
|
||||||
uint8_t g = G(col);
|
uint8_t g = G(col);
|
||||||
@ -837,6 +838,7 @@ void Segment::addPixelColor(int n, uint32_t color, bool fast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
CRGB pix = CRGB(getPixelColor(n)).nscale8_video(fade);
|
CRGB pix = CRGB(getPixelColor(n)).nscale8_video(fade);
|
||||||
setPixelColor(n, pix);
|
setPixelColor(n, pix);
|
||||||
}
|
}
|
||||||
@ -845,6 +847,7 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
|||||||
* fade out function, higher rate = quicker fade
|
* fade out function, higher rate = quicker fade
|
||||||
*/
|
*/
|
||||||
void Segment::fade_out(uint8_t rate) {
|
void Segment::fade_out(uint8_t rate) {
|
||||||
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
@ -882,7 +885,7 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
|
|
||||||
// fades all pixels to black using nscale8()
|
// fades all pixels to black using nscale8()
|
||||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||||
if (fadeBy == 0) return; // optimization - no scaling to apply
|
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
@ -897,7 +900,7 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
*/
|
*/
|
||||||
void Segment::blur(uint8_t blur_amount)
|
void Segment::blur(uint8_t blur_amount)
|
||||||
{
|
{
|
||||||
if (blur_amount == 0) return; // optimization: 0 means "don't blur"
|
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
// compatibility with 2D
|
// compatibility with 2D
|
||||||
@ -1071,7 +1074,7 @@ void WS2812FX::finalizeInit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::service() {
|
void WS2812FX::service() {
|
||||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
unsigned long nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||||
now = nowUp + timebase;
|
now = nowUp + timebase;
|
||||||
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
||||||
bool doShow = false;
|
bool doShow = false;
|
||||||
@ -1089,7 +1092,6 @@ void WS2812FX::service() {
|
|||||||
// last condition ensures all solid segments are updated at the same time
|
// last condition ensures all solid segments are updated at the same time
|
||||||
if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
||||||
{
|
{
|
||||||
if (seg.grouping == 0) seg.grouping = 1; // sanity check
|
|
||||||
doShow = true;
|
doShow = true;
|
||||||
uint16_t delay = FRAMETIME;
|
uint16_t delay = FRAMETIME;
|
||||||
|
|
||||||
@ -1117,12 +1119,19 @@ void WS2812FX::service() {
|
|||||||
}
|
}
|
||||||
_virtualSegmentLength = 0;
|
_virtualSegmentLength = 0;
|
||||||
busses.setSegmentCCT(-1);
|
busses.setSegmentCCT(-1);
|
||||||
if(doShow) {
|
_isServicing = false;
|
||||||
|
_triggered = false;
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow effects."));
|
||||||
|
#endif
|
||||||
|
if (doShow) {
|
||||||
yield();
|
yield();
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
_triggered = false;
|
#ifdef WLED_DEBUG
|
||||||
_isServicing = false;
|
if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow strip."));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
||||||
@ -1159,31 +1168,25 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
|
|||||||
bool useWackyWS2815PowerModel = false;
|
bool useWackyWS2815PowerModel = false;
|
||||||
byte actualMilliampsPerLed = milliampsPerLed;
|
byte actualMilliampsPerLed = milliampsPerLed;
|
||||||
|
|
||||||
if(milliampsPerLed == 255) {
|
|
||||||
useWackyWS2815PowerModel = true;
|
|
||||||
actualMilliampsPerLed = 12; // from testing an actual strip
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ablMilliampsMax < 150 || actualMilliampsPerLed == 0) { //0 mA per LED and too low numbers turn off calculation
|
if (ablMilliampsMax < 150 || actualMilliampsPerLed == 0) { //0 mA per LED and too low numbers turn off calculation
|
||||||
currentMilliamps = 0;
|
currentMilliamps = 0;
|
||||||
return _brightness;
|
return _brightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t pLen = getLengthPhysical();
|
if (milliampsPerLed == 255) {
|
||||||
uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
|
useWackyWS2815PowerModel = true;
|
||||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; //100mA for ESP power
|
actualMilliampsPerLed = 12; // from testing an actual strip
|
||||||
if (powerBudget > puPerMilliamp * pLen) { //each LED uses about 1mA in standby, exclude that from power budget
|
|
||||||
powerBudget -= puPerMilliamp * pLen;
|
|
||||||
} else {
|
|
||||||
powerBudget = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t powerSum = 0; // could overflow if more than 22K LEDs (uint32_t MAX / 195075 PU per LED)
|
size_t powerBudget = (ablMilliampsMax - MA_FOR_ESP); //100mA for ESP power
|
||||||
|
|
||||||
|
size_t pLen = 0; //getLengthPhysical();
|
||||||
|
size_t powerSum = 0;
|
||||||
for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) {
|
for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) {
|
||||||
Bus *bus = busses.getBus(bNum);
|
Bus *bus = busses.getBus(bNum);
|
||||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
if (!IS_DIGITAL(bus->getType())) continue; //exclude non-digital network busses
|
||||||
uint16_t len = bus->getLength();
|
uint16_t len = bus->getLength();
|
||||||
|
pLen += len;
|
||||||
uint32_t busPowerSum = 0;
|
uint32_t busPowerSum = 0;
|
||||||
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
|
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
|
||||||
uint32_t c = bus->getPixelColor(i); // always returns original or restored color without brightness scaling
|
uint32_t c = bus->getPixelColor(i); // always returns original or restored color without brightness scaling
|
||||||
@ -1198,38 +1201,44 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
|
|||||||
|
|
||||||
if (bus->hasWhite()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
if (bus->hasWhite()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||||
busPowerSum *= 3;
|
busPowerSum *= 3;
|
||||||
busPowerSum = busPowerSum >> 2; //same as /= 4
|
busPowerSum >>= 2; //same as /= 4
|
||||||
}
|
}
|
||||||
powerSum += busPowerSum;
|
powerSum += busPowerSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t newBri = _brightness;
|
if (powerBudget > pLen) { //each LED uses about 1mA in standby, exclude that from power budget
|
||||||
uint32_t powerSumUnscaled = powerSum;
|
powerBudget -= pLen;
|
||||||
powerSum *= _brightness;
|
} else {
|
||||||
|
powerBudget = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (powerSum > powerBudget) { //scale brightness down to stay in current limit
|
// powerSum has all the values of channels summed (max would be pLen*765 as white is excluded) so convert to milliAmps
|
||||||
|
powerSum = (powerSum * actualMilliampsPerLed) / 765;
|
||||||
|
|
||||||
|
uint8_t newBri = _brightness;
|
||||||
|
if (powerSum * _brightness / 255 > powerBudget) { //scale brightness down to stay in current limit
|
||||||
float scale = (float)powerBudget / (float)powerSum;
|
float scale = (float)powerBudget / (float)powerSum;
|
||||||
uint16_t scaleI = scale * 255;
|
uint16_t scaleI = scale * 255;
|
||||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
||||||
newBri = scale8(_brightness, scaleB);
|
newBri = scale8(_brightness, scaleB);
|
||||||
}
|
}
|
||||||
currentMilliamps = (powerSumUnscaled * newBri) / puPerMilliamp;
|
currentMilliamps = (powerSum * newBri) / 255;
|
||||||
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
||||||
currentMilliamps += pLen; //add standby power back to estimate
|
currentMilliamps += pLen; //add standby power (1mA/LED) back to estimate
|
||||||
return newBri;
|
return newBri;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::show(void) {
|
void WS2812FX::show(void) {
|
||||||
|
// avoid race condition, caputre _callback value
|
||||||
|
show_callback callback = _callback;
|
||||||
|
if (callback) callback();
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
static unsigned long sumMicros = 0, sumCurrent = 0;
|
static unsigned long sumMicros = 0, sumCurrent = 0;
|
||||||
static size_t calls = 0;
|
static size_t calls = 0;
|
||||||
unsigned long microsStart = micros();
|
unsigned long microsStart = micros();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// avoid race condition, caputre _callback value
|
|
||||||
show_callback callback = _callback;
|
|
||||||
if (callback) callback();
|
|
||||||
|
|
||||||
uint8_t busBrightness = estimateCurrentAndLimitBri();
|
uint8_t busBrightness = estimateCurrentAndLimitBri();
|
||||||
busses.setBrightness(busBrightness);
|
busses.setBrightness(busBrightness);
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
@ -1240,21 +1249,22 @@ void WS2812FX::show(void) {
|
|||||||
// all of the data has been sent.
|
// all of the data has been sent.
|
||||||
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
||||||
busses.show();
|
busses.show();
|
||||||
unsigned long now = millis();
|
|
||||||
unsigned long diff = now - _lastShow;
|
|
||||||
uint16_t fpsCurr = 200;
|
|
||||||
if (diff > 0) fpsCurr = 1000 / diff;
|
|
||||||
_cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2;
|
|
||||||
_lastShow = now;
|
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
sumMicros += micros() - microsStart;
|
sumMicros += micros() - microsStart;
|
||||||
if (++calls == 100) {
|
if (++calls == 100) {
|
||||||
DEBUG_PRINTF("show calls: %d micros: %lu avg: %lu (current: %lu avg: %lu)\n", calls, sumMicros, sumMicros/calls, sumCurrent, sumCurrent/calls);
|
DEBUG_PRINTF("%d show calls: %lu[us] avg: %lu[us] (current: %lu[us] avg: %lu[us])\n", calls, sumMicros, sumMicros/calls, sumCurrent, sumCurrent/calls);
|
||||||
sumMicros = sumCurrent = 0;
|
sumMicros = sumCurrent = 0;
|
||||||
calls = 0;
|
calls = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
size_t diff = now - _lastShow;
|
||||||
|
size_t fpsCurr = 200;
|
||||||
|
if (diff > 0) fpsCurr = 1000 / diff;
|
||||||
|
_cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2;
|
||||||
|
_lastShow = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1431,6 +1441,7 @@ Segment& WS2812FX::getSegment(uint8_t id) {
|
|||||||
return _segments[id >= _segments.size() ? getMainSegmentId() : id]; // vectors
|
return _segments[id >= _segments.size() ? getMainSegmentId() : id]; // vectors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compatibility method (deprecated)
|
||||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) {
|
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) {
|
||||||
if (n >= _segments.size()) return;
|
if (n >= _segments.size()) return;
|
||||||
_segments[n].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
_segments[n].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
||||||
|
@ -128,11 +128,6 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
|||||||
|
|
||||||
void BusDigital::show() {
|
void BusDigital::show() {
|
||||||
if (!_valid) return;
|
if (!_valid) return;
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
static unsigned long sumMicros = 0;
|
|
||||||
static size_t calls = 0;
|
|
||||||
unsigned long microsStart = micros();
|
|
||||||
#endif
|
|
||||||
PolyBus::setBrightness(_busPtr, _iType, _bri);
|
PolyBus::setBrightness(_busPtr, _iType, _bri);
|
||||||
if (buffering) { // should be _data != nullptr, but that causes ~20% FPS drop
|
if (buffering) { // should be _data != nullptr, but that causes ~20% FPS drop
|
||||||
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
|
size_t channels = Bus::hasWhite(_type) + 3*Bus::hasRGB(_type);
|
||||||
@ -159,14 +154,6 @@ void BusDigital::show() {
|
|||||||
}
|
}
|
||||||
PolyBus::show(_busPtr, _iType);
|
PolyBus::show(_busPtr, _iType);
|
||||||
PolyBus::setBrightness(_busPtr, _iType, 255); // restore full brightness at bus level (setting unscaled pixel color)
|
PolyBus::setBrightness(_busPtr, _iType, 255); // restore full brightness at bus level (setting unscaled pixel color)
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
sumMicros += micros() - microsStart;
|
|
||||||
if (++calls == 100) {
|
|
||||||
DEBUG_PRINTF("Bus calls: %d micros: %lu avg: %lu\n", calls, sumMicros, sumMicros/calls);
|
|
||||||
sumMicros = 0;
|
|
||||||
calls = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BusDigital::canShow() {
|
bool BusDigital::canShow() {
|
||||||
|
@ -22,7 +22,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
|
|
||||||
int stop = elem["stop"] | -1;
|
int stop = elem["stop"] | -1;
|
||||||
|
|
||||||
// if using vectors use this code to append segment
|
// append segment
|
||||||
if (id >= strip.getSegmentsNum()) {
|
if (id >= strip.getSegmentsNum()) {
|
||||||
if (stop <= 0) return false; // ignore empty/inactive segments
|
if (stop <= 0) return false; // ignore empty/inactive segments
|
||||||
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
||||||
@ -110,7 +110,10 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
of = offsetAbs;
|
of = offsetAbs;
|
||||||
}
|
}
|
||||||
if (stop > start && of > len -1) of = len -1;
|
if (stop > start && of > len -1) of = len -1;
|
||||||
seg.setUp(start, stop, grp, spc, of, startY, stopY);
|
|
||||||
|
// update segment (delete if necessary)
|
||||||
|
// we must not change segment dimensions during drawing of effects as that may produce undesired behaviour (crash)
|
||||||
|
seg.setUp(start, stop, grp, spc, of, startY, stopY, !strip.isServicing());
|
||||||
|
|
||||||
if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else
|
if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else
|
||||||
|
|
||||||
@ -468,12 +471,14 @@ void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, b
|
|||||||
if (segmentBounds) {
|
if (segmentBounds) {
|
||||||
root["start"] = seg.start;
|
root["start"] = seg.start;
|
||||||
root["stop"] = seg.stop;
|
root["stop"] = seg.stop;
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
root[F("startY")] = seg.startY;
|
root[F("startY")] = seg.startY;
|
||||||
root[F("stopY")] = seg.stopY;
|
root[F("stopY")] = seg.stopY;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (!forPreset) root["len"] = (seg.stop >= seg.start) ? (seg.stop - seg.start) : 0;
|
if (!forPreset) root["len"] = seg.stop - seg.start;
|
||||||
root["grp"] = seg.grouping;
|
root["grp"] = seg.grouping;
|
||||||
root[F("spc")] = seg.spacing;
|
root[F("spc")] = seg.spacing;
|
||||||
root[F("of")] = seg.offset;
|
root[F("of")] = seg.offset;
|
||||||
|
@ -23,7 +23,7 @@ void WLED::reset()
|
|||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
ws.closeAll(1012);
|
ws.closeAll(1012);
|
||||||
#endif
|
#endif
|
||||||
long dly = millis();
|
unsigned long dly = millis();
|
||||||
while (millis() - dly < 450) {
|
while (millis() - dly < 450) {
|
||||||
yield(); // enough time to send response to client
|
yield(); // enough time to send response to client
|
||||||
}
|
}
|
||||||
@ -36,13 +36,17 @@ void WLED::loop()
|
|||||||
{
|
{
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
static unsigned long lastRun = 0;
|
static unsigned long lastRun = 0;
|
||||||
size_t loopDelay = (millis() - lastRun);
|
unsigned long loopMillis = millis();
|
||||||
|
size_t loopDelay = loopMillis - lastRun;
|
||||||
if (lastRun == 0) loopDelay=0; // startup - don't have valid data from last run.
|
if (lastRun == 0) loopDelay=0; // startup - don't have valid data from last run.
|
||||||
if (loopDelay > 2) DEBUG_PRINTF("Loop delayed more than %dms.\n", loopDelay);
|
if (loopDelay > 2) DEBUG_PRINTF("Loop delayed more than %ums.\n", loopDelay);
|
||||||
|
static unsigned long maxLoopMillis = 0;
|
||||||
|
static size_t avgLoopMillis = 0;
|
||||||
static unsigned long maxUsermodMillis = 0;
|
static unsigned long maxUsermodMillis = 0;
|
||||||
static size_t avgUsermodMillis = 0;
|
static size_t avgUsermodMillis = 0;
|
||||||
static unsigned long maxStripMillis = 0;
|
static unsigned long maxStripMillis = 0;
|
||||||
static size_t avgStripMillis = 0;
|
static size_t avgStripMillis = 0;
|
||||||
|
unsigned long stripMillis;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
handleTime();
|
handleTime();
|
||||||
@ -84,6 +88,9 @@ void WLED::loop()
|
|||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
stripMillis = millis();
|
||||||
|
#endif
|
||||||
if (!realtimeMode || realtimeOverride || (realtimeMode && useMainSegmentOnly)) // block stuff if WARLS/Adalight is enabled
|
if (!realtimeMode || realtimeOverride || (realtimeMode && useMainSegmentOnly)) // block stuff if WARLS/Adalight is enabled
|
||||||
{
|
{
|
||||||
if (apActive) dnsServer.processNextRequest();
|
if (apActive) dnsServer.processNextRequest();
|
||||||
@ -102,22 +109,18 @@ void WLED::loop()
|
|||||||
handlePresets();
|
handlePresets();
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
unsigned long stripMillis = millis();
|
|
||||||
#endif
|
|
||||||
if (!offMode || strip.isOffRefreshRequired())
|
if (!offMode || strip.isOffRefreshRequired())
|
||||||
strip.service();
|
strip.service();
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
else if (!noWifiSleep)
|
else if (!noWifiSleep)
|
||||||
delay(1); //required to make sure ESP enters modem sleep (see #1184)
|
delay(1); //required to make sure ESP enters modem sleep (see #1184)
|
||||||
#endif
|
#endif
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
stripMillis = millis() - stripMillis;
|
|
||||||
if (stripMillis > 50) DEBUG_PRINTLN("Slow strip.");
|
|
||||||
avgStripMillis += stripMillis;
|
|
||||||
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
stripMillis = millis() - stripMillis;
|
||||||
|
avgStripMillis += stripMillis;
|
||||||
|
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
|
||||||
|
#endif
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@ -186,8 +189,31 @@ void WLED::loop()
|
|||||||
handleWs();
|
handleWs();
|
||||||
handleStatusLED();
|
handleStatusLED();
|
||||||
|
|
||||||
|
toki.resetTick();
|
||||||
|
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
|
// we finished our mainloop, reset the watchdog timer
|
||||||
|
if (!strip.isUpdating())
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
#else
|
||||||
|
ESP.wdtFeed();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration
|
||||||
|
reset();
|
||||||
|
|
||||||
// DEBUG serial logging (every 30s)
|
// DEBUG serial logging (every 30s)
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
|
loopMillis = millis() - loopMillis;
|
||||||
|
if (loopMillis > 30) {
|
||||||
|
DEBUG_PRINTF("Loop took %lums.\n", loopMillis);
|
||||||
|
DEBUG_PRINTF("Usermods took %lums.\n", usermodMillis);
|
||||||
|
DEBUG_PRINTF("Strip took %lums.\n", stripMillis);
|
||||||
|
}
|
||||||
|
avgLoopMillis += loopMillis;
|
||||||
|
if (loopMillis > maxLoopMillis) maxLoopMillis = loopMillis;
|
||||||
if (millis() - debugTime > 29999) {
|
if (millis() - debugTime > 29999) {
|
||||||
DEBUG_PRINTLN(F("---DEBUG INFO---"));
|
DEBUG_PRINTLN(F("---DEBUG INFO---"));
|
||||||
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
||||||
@ -210,11 +236,13 @@ void WLED::loop()
|
|||||||
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
|
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
|
||||||
if (loops > 0) { // avoid division by zero
|
if (loops > 0) { // avoid division by zero
|
||||||
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
|
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
|
||||||
|
DEBUG_PRINT(F("Loop time[ms]: ")); DEBUG_PRINT(avgLoopMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxLoopMillis);
|
||||||
DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
|
DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
|
||||||
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
|
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
|
||||||
}
|
}
|
||||||
strip.printSize();
|
strip.printSize();
|
||||||
loops = 0;
|
loops = 0;
|
||||||
|
maxLoopMillis = 0;
|
||||||
maxUsermodMillis = 0;
|
maxUsermodMillis = 0;
|
||||||
maxStripMillis = 0;
|
maxStripMillis = 0;
|
||||||
avgUsermodMillis = 0;
|
avgUsermodMillis = 0;
|
||||||
@ -224,20 +252,6 @@ void WLED::loop()
|
|||||||
loops++;
|
loops++;
|
||||||
lastRun = millis();
|
lastRun = millis();
|
||||||
#endif // WLED_DEBUG
|
#endif // WLED_DEBUG
|
||||||
toki.resetTick();
|
|
||||||
|
|
||||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
|
||||||
// we finished our mainloop, reset the watchdog timer
|
|
||||||
if (!strip.isUpdating())
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_task_wdt_reset();
|
|
||||||
#else
|
|
||||||
ESP.wdtFeed();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WLED::enableWatchdog() {
|
void WLED::enableWatchdog() {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2307090
|
#define VERSION 2307120
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -513,7 +513,7 @@ WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use i
|
|||||||
// wifi
|
// wifi
|
||||||
WLED_GLOBAL bool apActive _INIT(false);
|
WLED_GLOBAL bool apActive _INIT(false);
|
||||||
WLED_GLOBAL bool forceReconnect _INIT(false);
|
WLED_GLOBAL bool forceReconnect _INIT(false);
|
||||||
WLED_GLOBAL uint32_t lastReconnectAttempt _INIT(0);
|
WLED_GLOBAL unsigned long lastReconnectAttempt _INIT(0);
|
||||||
WLED_GLOBAL bool interfacesInited _INIT(false);
|
WLED_GLOBAL bool interfacesInited _INIT(false);
|
||||||
WLED_GLOBAL bool wasConnected _INIT(false);
|
WLED_GLOBAL bool wasConnected _INIT(false);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user