Merge 'blazoncek/dev' into 0_14

1-click presets
Bugfix for 1D
virtual strips POC for 1D effects
global SPI MISO pin
This commit is contained in:
Blaz Kristan 2022-08-29 20:45:06 +02:00
commit d28d2c57e4
15 changed files with 3486 additions and 3440 deletions

View File

@ -1036,7 +1036,6 @@ class AudioReactive : public Usermod {
// Only run the sampling code IF we're not in Receive mode or realtime mode
if (!(audioSyncEnabled & 0x02) && !disableSoundProcessing) {
bool agcEffect = false;
if (soundAgc > AGC_NUM_PRESETS) soundAgc = 0; // make sure that AGC preset is valid (to avoid array bounds violation)
unsigned long t_now = millis(); // remember current time

View File

@ -566,16 +566,14 @@ static const char _data_FX_MODE_SAW[] PROGMEM = "Saw@!,Width;!,!,;!;1d";
* Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
*/
uint16_t mode_twinkle(void) {
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : SEGMENT.virtualLength();
const uint16_t rows = SEGMENT.virtualHeight();
SEGMENT.fill(SEGCOLOR(1));
//SEGMENT.fill(SEGCOLOR(1));
SEGMENT.fade_out(224);
uint32_t cycleTime = 20 + (255 - SEGMENT.speed)*5;
uint32_t it = strip.now / cycleTime;
if (it != SEGENV.step)
{
uint16_t maxOn = map(SEGMENT.intensity, 0, 255, 1, cols*rows-1); // make sure at least one LED is on
uint16_t maxOn = map(SEGMENT.intensity, 0, 255, 1, SEGLEN); // make sure at least one LED is on
if (SEGENV.aux0 >= maxOn)
{
SEGENV.aux0 = 0;
@ -587,20 +585,17 @@ uint16_t mode_twinkle(void) {
uint16_t PRNG16 = SEGENV.aux1;
for (int i = 0; i < SEGENV.aux0; i++)
for (uint16_t i = 0; i < SEGENV.aux0; i++)
{
PRNG16 = (uint16_t)(PRNG16 * 2053) + 13849; // next 'random' number
uint32_t p = ((uint32_t)cols*rows * (uint32_t)PRNG16) >> 16;
uint16_t j = p % cols;
uint16_t k = p / cols;
uint32_t col = SEGMENT.color_from_palette(map(p, 0, cols*rows, 0, 255), false, PALETTE_SOLID_WRAP, 0);
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, col);
else SEGMENT.setPixelColor(j, col);
uint32_t p = (uint32_t)SEGLEN * (uint32_t)PRNG16;
uint16_t j = p >> 16;
SEGMENT.setPixelColor(j, SEGMENT.color_from_palette(j, true, PALETTE_SOLID_WRAP, 0));
}
return FRAMETIME;
}
static const char _data_FX_MODE_TWINKLE[] PROGMEM = "Twinkle@!,;!,!,;!;1d,2d"; //pixels
static const char _data_FX_MODE_TWINKLE[] PROGMEM = "Twinkle@!,;!,!,;!;mp12=0,1d"; //pixels
/*
@ -663,7 +658,7 @@ static const char _data_FX_MODE_DISSOLVE_RANDOM[] PROGMEM = "Dissolve Rnd@Repeat
* Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
*/
uint16_t mode_sparkle(void) {
for (int i = 0; i < SEGLEN; i++) {
for(int i = 0; i < SEGLEN; i++) {
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1));
}
uint32_t cycleTime = 10 + (255 - SEGMENT.speed)*2;
@ -671,15 +666,13 @@ uint16_t mode_sparkle(void) {
if (it != SEGENV.step)
{
SEGENV.aux0 = random16(SEGLEN); // aux0 stores the random led index
SEGENV.aux1 = random16(0,SEGMENT.virtualHeight()-1);
SEGENV.step = it;
}
if (strip.isMatrix) SEGMENT.setPixelColorXY(SEGENV.aux0, SEGENV.aux1, SEGCOLOR(0));
else SEGMENT.setPixelColor(SEGENV.aux0, SEGCOLOR(0));
SEGMENT.setPixelColor(SEGENV.aux0, SEGCOLOR(0));
return FRAMETIME;
}
static const char _data_FX_MODE_SPARKLE[] PROGMEM = "Sparkle@!,;!,!,;!;1d,2d";
static const char _data_FX_MODE_SPARKLE[] PROGMEM = "Sparkle@!,;!,!,;!;mp12=0,1d";
/*
@ -687,21 +680,20 @@ static const char _data_FX_MODE_SPARKLE[] PROGMEM = "Sparkle@!,;!,!,;!;1d,2d";
* Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
*/
uint16_t mode_flash_sparkle(void) {
for (int i = 0; i < SEGLEN; i++) {
for(uint16_t i = 0; i < SEGLEN; i++) {
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
if (strip.now - SEGENV.aux0 > SEGENV.step) {
if(random8((255-SEGMENT.intensity) >> 4) == 0) {
if (strip.isMatrix) SEGMENT.setPixelColorXY(random16(SEGLEN), random16(0,SEGMENT.virtualHeight()-1), SEGCOLOR(1));
else SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1)); //flash
SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1)); //flash
}
SEGENV.step = strip.now;
SEGENV.aux0 = 255-SEGMENT.speed;
}
return FRAMETIME;
}
static const char _data_FX_MODE_FLASH_SPARKLE[] PROGMEM = "Sparkle Dark@!,!;Bg,Fx,;!;1d,2d";
static const char _data_FX_MODE_FLASH_SPARKLE[] PROGMEM = "Sparkle Dark@!,!;Bg,Fx,;!;mp12=0,1d";
/*
@ -714,10 +706,9 @@ uint16_t mode_hyper_sparkle(void) {
}
if (strip.now - SEGENV.aux0 > SEGENV.step) {
if(random8((255-SEGMENT.intensity) >> 4) == 0) {
if (random8((255-SEGMENT.intensity) >> 4) == 0) {
for (int i = 0; i < MAX(1, SEGLEN/3); i++) {
if (strip.isMatrix) SEGMENT.setPixelColorXY(random16(SEGLEN), random16(0,SEGMENT.virtualHeight()), SEGCOLOR(1));
else SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1));
SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1));
}
}
SEGENV.step = strip.now;
@ -725,7 +716,7 @@ uint16_t mode_hyper_sparkle(void) {
}
return FRAMETIME;
}
static const char _data_FX_MODE_HYPER_SPARKLE[] PROGMEM = "Sparkle+@!,!;Bg,Fx,;!;1d,2d";
static const char _data_FX_MODE_HYPER_SPARKLE[] PROGMEM = "Sparkle+@!,!;Bg,Fx,;!;mp12=0,1d";
/*
@ -1350,7 +1341,7 @@ uint16_t police_base(uint32_t color1, uint32_t color2)
uint32_t it = strip.now / map(SEGMENT.speed, 0, 255, delay<<4, delay);
uint16_t offset = it % SEGLEN;
uint16_t width = ((SEGLEN*(SEGMENT.intensity+1))>>9); //max width is half the strip
uint16_t width = ((SEGLEN*(SEGMENT.intensity+1))>>9); //max width is half the strip
if (!width) width = 1;
for (int i = 0; i < width; i++) {
uint16_t indexR = (offset + i) % SEGLEN;
@ -1389,82 +1380,82 @@ static const char _data_FX_MODE_TWO_DOTS[] PROGMEM = "Two Dots@!,Dot size;1,2,Bg
typedef struct Flasher {
uint16_t stateStart;
uint8_t stateDur;
bool stateOn;
bool stateOn;
} flasher;
#define FLASHERS_PER_ZONE 6
#define MAX_SHIMMER 92
uint16_t mode_fairy() {
//set every pixel to a 'random' color from palette (using seed so it doesn't change between frames)
uint16_t PRNG16 = 5100 + strip.getCurrSegmentId();
for (int i = 0; i < SEGLEN; i++) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0));
}
//set every pixel to a 'random' color from palette (using seed so it doesn't change between frames)
uint16_t PRNG16 = 5100 + strip.getCurrSegmentId();
for (int i = 0; i < SEGLEN; i++) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0));
}
//amount of flasher pixels depending on intensity (0: none, 255: every LED)
if (SEGMENT.intensity == 0) return FRAMETIME;
uint8_t flasherDistance = ((255 - SEGMENT.intensity) / 28) +1; //1-10
uint16_t numFlashers = (SEGLEN / flasherDistance) +1;
uint16_t dataSize = sizeof(flasher) * numFlashers;
//amount of flasher pixels depending on intensity (0: none, 255: every LED)
if (SEGMENT.intensity == 0) return FRAMETIME;
uint8_t flasherDistance = ((255 - SEGMENT.intensity) / 28) +1; //1-10
uint16_t numFlashers = (SEGLEN / flasherDistance) +1;
uint16_t dataSize = sizeof(flasher) * numFlashers;
if (!SEGENV.allocateData(dataSize)) return FRAMETIME; //allocation failed
Flasher* flashers = reinterpret_cast<Flasher*>(SEGENV.data);
uint16_t now16 = strip.now & 0xFFFF;
Flasher* flashers = reinterpret_cast<Flasher*>(SEGENV.data);
uint16_t now16 = strip.now & 0xFFFF;
//Up to 11 flashers in one brightness zone, afterwards a new zone for every 6 flashers
uint16_t zones = numFlashers/FLASHERS_PER_ZONE;
if (!zones) zones = 1;
uint8_t flashersInZone = numFlashers/zones;
uint8_t flasherBri[FLASHERS_PER_ZONE*2 -1];
//Up to 11 flashers in one brightness zone, afterwards a new zone for every 6 flashers
uint16_t zones = numFlashers/FLASHERS_PER_ZONE;
if (!zones) zones = 1;
uint8_t flashersInZone = numFlashers/zones;
uint8_t flasherBri[FLASHERS_PER_ZONE*2 -1];
for (int z = 0; z < zones; z++) {
uint16_t flasherBriSum = 0;
uint16_t firstFlasher = z*flashersInZone;
if (z == zones-1) flashersInZone = numFlashers-(flashersInZone*(zones-1));
for (int z = 0; z < zones; z++) {
uint16_t flasherBriSum = 0;
uint16_t firstFlasher = z*flashersInZone;
if (z == zones-1) flashersInZone = numFlashers-(flashersInZone*(zones-1));
for (int f = firstFlasher; f < firstFlasher + flashersInZone; f++) {
uint16_t stateTime = now16 - flashers[f].stateStart;
//random on/off time reached, switch state
if (stateTime > flashers[f].stateDur * 10) {
flashers[f].stateOn = !flashers[f].stateOn;
if (flashers[f].stateOn) {
flashers[f].stateDur = 12 + random8(12 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms
} else {
flashers[f].stateDur = 20 + random8(6 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms
}
//flashers[f].stateDur = 51 + random8(2 + ((255 - SEGMENT.speed) >> 1));
flashers[f].stateStart = now16;
if (stateTime < 255) {
flashers[f].stateStart -= 255 -stateTime; //start early to get correct bri
flashers[f].stateDur += 26 - stateTime/10;
stateTime = 255 - stateTime;
} else {
stateTime = 0;
}
}
if (stateTime > 255) stateTime = 255; //for flasher brightness calculation, fades in first 255 ms of state
//flasherBri[f - firstFlasher] = (flashers[f].stateOn) ? 255-SEGMENT.gamma8((510 - stateTime) >> 1) : SEGMENT.gamma8((510 - stateTime) >> 1);
flasherBri[f - firstFlasher] = (flashers[f].stateOn) ? stateTime : 255 - (stateTime >> 0);
flasherBriSum += flasherBri[f - firstFlasher];
}
//dim factor, to create "shimmer" as other pixels get less voltage if a lot of flashers are on
uint8_t avgFlasherBri = flasherBriSum / flashersInZone;
uint8_t globalPeakBri = 255 - ((avgFlasherBri * MAX_SHIMMER) >> 8); //183-255, suitable for 1/5th of LEDs flashers
for (int f = firstFlasher; f < firstFlasher + flashersInZone; f++) {
uint16_t stateTime = now16 - flashers[f].stateStart;
//random on/off time reached, switch state
if (stateTime > flashers[f].stateDur * 10) {
flashers[f].stateOn = !flashers[f].stateOn;
if (flashers[f].stateOn) {
flashers[f].stateDur = 12 + random8(12 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms
} else {
flashers[f].stateDur = 20 + random8(6 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms
}
//flashers[f].stateDur = 51 + random8(2 + ((255 - SEGMENT.speed) >> 1));
flashers[f].stateStart = now16;
if (stateTime < 255) {
flashers[f].stateStart -= 255 -stateTime; //start early to get correct bri
flashers[f].stateDur += 26 - stateTime/10;
stateTime = 255 - stateTime;
} else {
stateTime = 0;
}
}
if (stateTime > 255) stateTime = 255; //for flasher brightness calculation, fades in first 255 ms of state
//flasherBri[f - firstFlasher] = (flashers[f].stateOn) ? 255-SEGMENT.gamma8((510 - stateTime) >> 1) : SEGMENT.gamma8((510 - stateTime) >> 1);
flasherBri[f - firstFlasher] = (flashers[f].stateOn) ? stateTime : 255 - (stateTime >> 0);
flasherBriSum += flasherBri[f - firstFlasher];
}
//dim factor, to create "shimmer" as other pixels get less voltage if a lot of flashers are on
uint8_t avgFlasherBri = flasherBriSum / flashersInZone;
uint8_t globalPeakBri = 255 - ((avgFlasherBri * MAX_SHIMMER) >> 8); //183-255, suitable for 1/5th of LEDs flashers
for (int f = firstFlasher; f < firstFlasher + flashersInZone; f++) {
uint8_t bri = (flasherBri[f - firstFlasher] * globalPeakBri) / 255;
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
uint16_t flasherPos = f*flasherDistance;
SEGMENT.setPixelColor(flasherPos, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0), bri));
for (int i = flasherPos+1; i < flasherPos+flasherDistance && i < SEGLEN; i++) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0, globalPeakBri));
}
}
}
return FRAMETIME;
for (int f = firstFlasher; f < firstFlasher + flashersInZone; f++) {
uint8_t bri = (flasherBri[f - firstFlasher] * globalPeakBri) / 255;
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
uint16_t flasherPos = f*flasherDistance;
SEGMENT.setPixelColor(flasherPos, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0), bri));
for (int i = flasherPos+1; i < flasherPos+flasherDistance && i < SEGLEN; i++) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0, globalPeakBri));
}
}
}
return FRAMETIME;
}
static const char _data_FX_MODE_FAIRY[] PROGMEM = "Fairy";
@ -1474,46 +1465,46 @@ static const char _data_FX_MODE_FAIRY[] PROGMEM = "Fairy";
* Warning: Uses 4 bytes of segment data per pixel
*/
uint16_t mode_fairytwinkle() {
uint16_t dataSize = sizeof(flasher) * SEGLEN;
uint16_t dataSize = sizeof(flasher) * SEGLEN;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
Flasher* flashers = reinterpret_cast<Flasher*>(SEGENV.data);
uint16_t now16 = strip.now & 0xFFFF;
uint16_t PRNG16 = 5100 + strip.getCurrSegmentId();
Flasher* flashers = reinterpret_cast<Flasher*>(SEGENV.data);
uint16_t now16 = strip.now & 0xFFFF;
uint16_t PRNG16 = 5100 + strip.getCurrSegmentId();
uint16_t riseFallTime = 400 + (255-SEGMENT.speed)*3;
uint16_t maxDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + 13 + ((255 - SEGMENT.intensity) >> 1);
uint16_t riseFallTime = 400 + (255-SEGMENT.speed)*3;
uint16_t maxDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + 13 + ((255 - SEGMENT.intensity) >> 1);
for (int f = 0; f < SEGLEN; f++) {
uint16_t stateTime = now16 - flashers[f].stateStart;
//random on/off time reached, switch state
if (stateTime > flashers[f].stateDur * 100) {
flashers[f].stateOn = !flashers[f].stateOn;
bool init = !flashers[f].stateDur;
if (flashers[f].stateOn) {
flashers[f].stateDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +1;
} else {
flashers[f].stateDur = riseFallTime/100 + random8(3 + ((255 - SEGMENT.speed) >> 6)) +1;
}
flashers[f].stateStart = now16;
stateTime = 0;
if (init) {
flashers[f].stateStart -= riseFallTime; //start lit
flashers[f].stateDur = riseFallTime/100 + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +5; //fire up a little quicker
stateTime = riseFallTime;
}
}
if (flashers[f].stateOn && flashers[f].stateDur > maxDur) flashers[f].stateDur = maxDur; //react more quickly on intensity change
if (stateTime > riseFallTime) stateTime = riseFallTime; //for flasher brightness calculation, fades in first 255 ms of state
uint8_t fadeprog = 255 - ((stateTime * 255) / riseFallTime);
uint8_t flasherBri = (flashers[f].stateOn) ? 255-gamma8(fadeprog) : gamma8(fadeprog);
uint16_t lastR = PRNG16;
uint16_t diff = 0;
while (diff < 0x4000) { //make sure colors of two adjacent LEDs differ enough
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
diff = (PRNG16 > lastR) ? PRNG16 - lastR : lastR - PRNG16;
}
SEGMENT.setPixelColor(f, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0), flasherBri));
}
for (int f = 0; f < SEGLEN; f++) {
uint16_t stateTime = now16 - flashers[f].stateStart;
//random on/off time reached, switch state
if (stateTime > flashers[f].stateDur * 100) {
flashers[f].stateOn = !flashers[f].stateOn;
bool init = !flashers[f].stateDur;
if (flashers[f].stateOn) {
flashers[f].stateDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +1;
} else {
flashers[f].stateDur = riseFallTime/100 + random8(3 + ((255 - SEGMENT.speed) >> 6)) +1;
}
flashers[f].stateStart = now16;
stateTime = 0;
if (init) {
flashers[f].stateStart -= riseFallTime; //start lit
flashers[f].stateDur = riseFallTime/100 + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +5; //fire up a little quicker
stateTime = riseFallTime;
}
}
if (flashers[f].stateOn && flashers[f].stateDur > maxDur) flashers[f].stateDur = maxDur; //react more quickly on intensity change
if (stateTime > riseFallTime) stateTime = riseFallTime; //for flasher brightness calculation, fades in first 255 ms of state
uint8_t fadeprog = 255 - ((stateTime * 255) / riseFallTime);
uint8_t flasherBri = (flashers[f].stateOn) ? 255-gamma8(fadeprog) : gamma8(fadeprog);
uint16_t lastR = PRNG16;
uint16_t diff = 0;
while (diff < 0x4000) { //make sure colors of two adjacent LEDs differ enough
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; //next 'random' number
diff = (PRNG16 > lastR) ? PRNG16 - lastR : lastR - PRNG16;
}
SEGMENT.setPixelColor(f, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(PRNG16 >> 8, false, false, 0), flasherBri));
}
return FRAMETIME;
}
static const char _data_FX_MODE_FAIRYTWINKLE[] PROGMEM = "Fairy Twinkle@;;;mp12=0,1d"; //pixels
@ -2209,19 +2200,14 @@ static const char _data_FX_MODE_NOISE16_4[] PROGMEM = "Noise 4@!,!;!,!,!;!;1d";
//based on https://gist.github.com/kriegsman/5408ecd397744ba0393e
uint16_t mode_colortwinkle()
{
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
uint16_t dataSize = (cols*rows+7) >> 3; //1 bit per LED
uint16_t dataSize = (SEGLEN+7) >> 3; //1 bit per LED
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
CRGB fastled_col, prev;
fract8 fadeUpAmount = strip.getBrightness()>28 ? 8 + (SEGMENT.speed>>2) : 68-strip.getBrightness();
fract8 fadeDownAmount = strip.getBrightness()>28 ? 8 + (SEGMENT.speed>>3) : 68-strip.getBrightness();
for (int i = 0; i < rows*cols; i++) {
uint16_t j = i % cols, k = i / cols;
fastled_col = CRGB(strip.isMatrix ? SEGMENT.getPixelColorXY(j, k) : SEGMENT.getPixelColor(i)); // TODO
for (uint16_t i = 0; i < SEGLEN; i++) {
fastled_col = SEGMENT.getPixelColor(i);
prev = fastled_col;
uint16_t index = i >> 3;
uint8_t bitNum = i & 0x07;
@ -2235,36 +2221,28 @@ uint16_t mode_colortwinkle()
if (fastled_col.red == 255 || fastled_col.green == 255 || fastled_col.blue == 255) {
bitWrite(SEGENV.data[index], bitNum, false);
}
SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, fastled_col);
else SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
uint32_t col = strip.isMatrix ? SEGMENT.getPixelColorXY(j, k) : SEGMENT.getPixelColor(i); // TODO
if (CRGB(col) == prev) { //fix "stuck" pixels
if (SEGMENT.getPixelColor(i) == RGBW32(prev.r, prev.g, prev.b, 0)) { //fix "stuck" pixels
fastled_col += fastled_col;
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, fastled_col);
else SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
SEGMENT.setPixelColor(i, fastled_col);
}
} else {
fastled_col.nscale8(255 - fadeDownAmount);
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, fastled_col);
else SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
SEGMENT.setPixelColor(i, fastled_col);
}
}
for (int j = 0; j <= rows*cols / 50; j++) {
for (uint16_t j = 0; j <= SEGLEN / 50; j++) {
if (random8() <= SEGMENT.intensity) {
for (size_t times = 0; times < 5; times++) { //attempt to spawn a new pixel 5 times
uint16_t i = random16(rows*cols);
uint16_t j = i % cols, k = i / cols;
uint32_t col = strip.isMatrix ? SEGMENT.getPixelColorXY(j, k) : SEGMENT.getPixelColor(i); // TODO
if (col == 0) {
for (uint8_t times = 0; times < 5; times++) { //attempt to spawn a new pixel 5 times
int i = random16(SEGLEN);
if (SEGMENT.getPixelColor(i) == 0) {
fastled_col = ColorFromPalette(SEGPALETTE, random8(), 64, NOBLEND);
uint16_t index = i >> 3;
uint8_t bitNum = i & 0x07;
bitWrite(SEGENV.data[index], bitNum, true);
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, fastled_col);
else SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
SEGMENT.setPixelColor(i, fastled_col);
break; //only spawn 1 new pixel per frame per 50 LEDs
}
}
@ -2272,7 +2250,7 @@ uint16_t mode_colortwinkle()
}
return FRAMETIME_FIXED;
}
static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade speed,Spawn speed;1,2,3;!;1d,2d"; //pixels
static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade speed,Spawn speed;1,2,3;!;mp12=0,1d"; //pixels
//Calm effect, like a lake at night
@ -2651,13 +2629,13 @@ static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat";
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
#define HALLOWEEN_EYE_SPACE (2*MAX(1,SEGLEN>>5))
#define HALLOWEEN_EYE_WIDTH MAX(1,SEGLEN>>5)
uint16_t mode_halloween_eyes()
{
{
const uint16_t maxWidth = strip.isMatrix ? SEGMENT.virtualWidth() : SEGLEN;
const uint16_t HALLOWEEN_EYE_SPACE = MAX(2, strip.isMatrix ? SEGMENT.virtualWidth()>>4: SEGLEN>>5);
const uint16_t HALLOWEEN_EYE_WIDTH = HALLOWEEN_EYE_SPACE/2;
uint16_t eyeLength = (2*HALLOWEEN_EYE_WIDTH) + HALLOWEEN_EYE_SPACE;
if (eyeLength > SEGLEN) return mode_static(); //bail if segment too short
if (eyeLength >= maxWidth) return mode_static(); //bail if segment too short
SEGMENT.fill(SEGCOLOR(1)); //fill background
@ -2666,7 +2644,7 @@ uint16_t mode_halloween_eyes()
if (stateTime == 0) stateTime = 2000;
if (state == 0) { //spawn eyes
SEGENV.aux0 = random16(0, SEGLEN - eyeLength); //start pos
SEGENV.aux0 = random16(0, maxWidth - eyeLength - 1); //start pos
SEGENV.aux1 = random8(); //color
if (strip.isMatrix) SEGMENT.offset = random16(SEGMENT.virtualHeight()-1); // a hack: reuse offset since it is not used in matrices
state = 1;
@ -2696,9 +2674,9 @@ uint16_t mode_halloween_eyes()
if (state > 2) state = 0;
if (state < 2) {
stateTime = 100 + (255 - SEGMENT.intensity)*10; //eye fade time
stateTime = 100 + SEGMENT.intensity*10; //eye fade time
} else {
uint16_t eyeOffTimeBase = (255 - SEGMENT.speed)*10;
uint16_t eyeOffTimeBase = (256 - SEGMENT.speed)*10;
stateTime = eyeOffTimeBase + random16(eyeOffTimeBase);
}
SEGENV.step = strip.now;
@ -2818,59 +2796,69 @@ typedef struct Ball {
*/
uint16_t mode_bouncing_balls(void) {
//allocate segment data
uint16_t maxNumBalls = 16;
const uint16_t strips = SEGMENT.nrOfVStrips(); // adapt for 2D
const size_t maxNumBalls = 16;
uint16_t dataSize = sizeof(ball) * maxNumBalls;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed
Ball* balls = reinterpret_cast<Ball*>(SEGENV.data);
// number of balls based on intensity setting to max of 7 (cycles colors)
// non-chosen color is a random color
uint16_t numBalls = int(((SEGMENT.intensity * (maxNumBalls - 0.8f)) / 255) + 1);
float gravity = -9.81; // standard value of gravity
float impactVelocityStart = sqrt( -2 * gravity);
unsigned long time = millis();
SEGMENT.fill(SEGCOLOR(2) ? BLACK : SEGCOLOR(1));
if (SEGENV.call == 0) {
for (size_t i = 0; i < maxNumBalls; i++) balls[i].lastBounceTime = time;
}
bool hasCol2 = SEGCOLOR(2);
SEGMENT.fill(hasCol2 ? BLACK : SEGCOLOR(1));
for (size_t i = 0; i < numBalls; i++) {
float timeSinceLastBounce = (time - balls[i].lastBounceTime)/((255-SEGMENT.speed)*8/256 +1);
float timeSec = timeSinceLastBounce/1000.0f;
balls[i].height = 0.5 * gravity * (timeSec * timeSec) + balls[i].impactVelocity * timeSec; // avoid use pow(x, 2) - its extremely slow !
// virtualStrip idea by @ewowi (Ewoud Wijma)
struct virtualStrip {
static void runStrip(size_t stripNr, Ball* balls) {
// number of balls based on intensity setting to max of 7 (cycles colors)
// non-chosen color is a random color
uint16_t numBalls = (SEGMENT.intensity * (maxNumBalls - 1)) / 255 + 1; // minimum 1 ball
const float gravity = -9.81; // standard value of gravity
const bool hasCol2 = SEGCOLOR(2);
const unsigned long time = millis();
if (balls[i].height < 0) { //start bounce
balls[i].height = 0;
//damping for better effect using multiple balls
float dampening = 0.90 - float(i)/float(numBalls * numBalls); // avoid use pow(x, 2) - its extremely slow !
balls[i].impactVelocity = dampening * balls[i].impactVelocity;
balls[i].lastBounceTime = time;
if (SEGENV.call == 0) {
for (size_t i = 0; i < maxNumBalls; i++) balls[i].lastBounceTime = time;
}
for (size_t i = 0; i < numBalls; i++) {
float timeSinceLastBounce = (time - balls[i].lastBounceTime)/((255-SEGMENT.speed)/64 +1);
float timeSec = timeSinceLastBounce/1000.0f;
balls[i].height = (0.5f * gravity * timeSec + balls[i].impactVelocity) * timeSec; // avoid use pow(x, 2) - its extremely slow !
if (balls[i].impactVelocity < 0.015) {
balls[i].impactVelocity = impactVelocityStart;
if (balls[i].height <= 0.0f) {
balls[i].height = 0.0f;
//damping for better effect using multiple balls
float dampening = 0.9f - float(i)/float(numBalls * numBalls); // avoid use pow(x, 2) - its extremely slow !
balls[i].impactVelocity = dampening * balls[i].impactVelocity;
balls[i].lastBounceTime = time;
if (balls[i].impactVelocity < 0.015f) {
float impactVelocityStart = sqrt(-2 * gravity) * random8(5,11)/10.0f; // randomize impact velocity
balls[i].impactVelocity = impactVelocityStart;
}
} else if (balls[i].height > 1.0f) {
continue; // do not draw OOB ball
}
uint32_t color = SEGCOLOR(0);
if (SEGMENT.palette) {
color = SEGMENT.color_wheel(i*(256/MAX(numBalls, 8)));
} else if (hasCol2) {
color = SEGCOLOR(i % NUM_COLORS);
}
int pos = roundf(balls[i].height * (SEGLEN - 1));
SEGMENT.setPixelColor(pos | int((stripNr+1)<<16), color); // encode virtual strip into index
//SEGMENT.setPixelColor(balls[i].height + (stripNr+1)*10.0f, color);
}
}
uint32_t color = SEGCOLOR(0);
if (SEGMENT.palette) {
color = SEGMENT.color_wheel(i*(256/MAX(numBalls, 8)));
} else if (hasCol2) {
color = SEGCOLOR(i % NUM_COLORS);
}
};
uint16_t pos = roundf(balls[i].height * (SEGLEN - 1));
SEGMENT.setPixelColor(pos, color);
}
for (int stripNr=0; stripNr<strips; stripNr++)
virtualStrip::runStrip(stripNr, &balls[stripNr * maxNumBalls]);
return FRAMETIME;
}
static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravity,# of balls;!,!,;!;mp12=2,1d"; //circle
static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravity,# of balls;!,!,!;!;mp12=1,1d"; //bar
/*
@ -2933,18 +2921,14 @@ uint16_t mode_glitter()
{
mode_palette();
if (strip.isMatrix) {
uint16_t height = SEGMENT.virtualHeight();
uint16_t width = SEGMENT.virtualWidth();
for (int i = 0; i<height; i++) {
if (SEGMENT.intensity > random8()) SEGMENT.setPixelColorXY(random16(width-1), i, ULTRAWHITE);
}
} else
if (SEGMENT.intensity > random8()) SEGMENT.setPixelColor(random16(SEGLEN), ULTRAWHITE);
if (SEGMENT.intensity > random8())
{
SEGMENT.setPixelColor(random16(SEGLEN), ULTRAWHITE);
}
return FRAMETIME;
}
static const char _data_FX_MODE_GLITTER[] PROGMEM = "Glitter@,!;!,!,!;!;1d,2d"; //pixels
static const char _data_FX_MODE_GLITTER[] PROGMEM = "Glitter@,!;!,!,!;!;mp12=0,1d"; //pixels
//each needs 19 bytes
@ -3574,9 +3558,9 @@ static const char _data_FX_MODE_PLASMA[] PROGMEM = "Plasma@Phase,;1,2,3;!;1d";
*/
uint16_t mode_percent(void) {
uint8_t percent = SEGMENT.intensity;
uint8_t percent = SEGMENT.intensity;
percent = constrain(percent, 0, 200);
uint16_t active_leds = (percent < 100) ? SEGLEN * percent / 100.0
uint16_t active_leds = (percent < 100) ? SEGLEN * percent / 100.0
: SEGLEN * (200 - percent) / 100.0;
uint8_t size = (1 + ((SEGMENT.speed * SEGLEN) >> 11));
@ -3584,22 +3568,22 @@ uint16_t mode_percent(void) {
if (percent < 100) {
for (int i = 0; i < SEGLEN; i++) {
if (i < SEGENV.aux1) {
if (i < SEGENV.aux1) {
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
else {
}
else {
SEGMENT.setPixelColor(i, SEGCOLOR(1));
}
}
}
}
} else {
for (int i = 0; i < SEGLEN; i++) {
if (i < (SEGLEN - SEGENV.aux1)) {
if (i < (SEGLEN - SEGENV.aux1)) {
SEGMENT.setPixelColor(i, SEGCOLOR(1));
}
else {
}
else {
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
}
}
}
}
}
if(active_leds > SEGENV.aux1) { // smooth transition to the target value
@ -3770,18 +3754,14 @@ uint16_t mode_solid_glitter()
{
SEGMENT.fill(SEGCOLOR(0));
if (strip.isMatrix) {
uint16_t height = SEGMENT.virtualHeight();
uint16_t width = SEGMENT.virtualWidth();
for (int i = 0; i<height; i++) {
if (SEGMENT.intensity > random8()) SEGMENT.setPixelColorXY(random16(width-1), i, ULTRAWHITE);
}
} else
if (SEGMENT.intensity > random8()) SEGMENT.setPixelColor(random16(SEGLEN), ULTRAWHITE);
if (SEGMENT.intensity > random8())
{
SEGMENT.setPixelColor(random16(SEGLEN), ULTRAWHITE);
}
return FRAMETIME;
}
static const char _data_FX_MODE_SOLID_GLITTER[] PROGMEM = "Solid Glitter@,!;!,,;0;1d,2d";
static const char _data_FX_MODE_SOLID_GLITTER[] PROGMEM = "Solid Glitter@,!;!,,;0;mp12=0,1d";
/*
@ -3793,7 +3773,7 @@ uint16_t mode_sunrise() {
//speed 60 - 120 : sunset time in minutes - 60;
//speed above: "breathing" rise and set
if (SEGENV.call == 0 || SEGMENT.speed != SEGENV.aux0) {
SEGENV.step = millis(); //save starting time, millis() because now can change from sync
SEGENV.step = millis(); //save starting time, millis() because now can change from sync
SEGENV.aux0 = SEGMENT.speed;
}
@ -3803,15 +3783,15 @@ uint16_t mode_sunrise() {
uint32_t s10SinceStart = (millis() - SEGENV.step) /100; //tenths of seconds
if (SEGMENT.speed > 120) { //quick sunrise and sunset
uint16_t counter = (strip.now >> 1) * (((SEGMENT.speed -120) >> 1) +1);
stage = triwave16(counter);
uint16_t counter = (strip.now >> 1) * (((SEGMENT.speed -120) >> 1) +1);
stage = triwave16(counter);
} else if (SEGMENT.speed) { //sunrise
uint8_t durMins = SEGMENT.speed;
if (durMins > 60) durMins -= 60;
uint32_t s10Target = durMins * 600;
if (s10SinceStart > s10Target) s10SinceStart = s10Target;
stage = map(s10SinceStart, 0, s10Target, 0, 0xFFFF);
if (SEGMENT.speed > 60) stage = 0xFFFF - stage; //sunset
uint8_t durMins = SEGMENT.speed;
if (durMins > 60) durMins -= 60;
uint32_t s10Target = durMins * 600;
if (s10SinceStart > s10Target) s10SinceStart = s10Target;
stage = map(s10SinceStart, 0, s10Target, 0, 0xFFFF);
if (SEGMENT.speed > 60) stage = 0xFFFF - stage; //sunset
}
for (int i = 0; i <= SEGLEN/2; i++)
@ -3879,24 +3859,18 @@ static const char _data_FX_MODE_PHASEDNOISE[] PROGMEM = "Phased Noise";
uint16_t mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline.
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
for (int i = 0; i<rows*cols; i++) {
uint16_t j = i % rows, k = i / rows;
uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work.
for (int i = 0; i<SEGLEN; i++) {
uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work.
uint8_t pixBri = sin8(ranstart + 16 * strip.now/(256-SEGMENT.speed));
if (random8() > SEGMENT.intensity) pixBri = 0;
uint32_t col = color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8() + strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri);
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, col);
else SEGMENT.setPixelColor(i, col);
SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri));
}
return FRAMETIME;
}
static const char _data_FX_MODE_TWINKLEUP[] PROGMEM = "Twinkleup@!,Intensity;!,!,;!;1d,2d";
static const char _data_FX_MODE_TWINKLEUP[] PROGMEM = "Twinkleup@!,Intensity;!,!,;!;mp12=0,1d";
// Peaceful noise that's slow and with gradually changing palettes. Does not support WLED palettes or default colours or controls.

View File

@ -339,9 +339,9 @@
typedef enum mapping1D2D {
M12_Pixels = 0,
M12_VerticalBar = 1,
M12_Circle = 2,
M12_Block = 3
M12_pBar = 1,
M12_pArc = 2,
M12_pCorner = 3
} mapping1D2D_t;
// segment, 72 bytes
@ -551,7 +551,7 @@ typedef struct Segment {
void setPixelColor(float i, uint32_t c, bool aa = true);
void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
uint32_t getPixelColor(uint16_t i);
uint32_t getPixelColor(int i);
// 1D support functions (some implement 2D as well)
void blur(uint8_t);
void fill(uint32_t c);
@ -570,6 +570,7 @@ typedef struct Segment {
// 2D matrix
uint16_t virtualWidth(void) const;
uint16_t virtualHeight(void) const;
uint16_t nrOfVStrips(void) const;
#ifndef WLED_DISABLE_2D
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[])
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
@ -678,8 +679,8 @@ class WS2812FX { // 96 bytes
_length(DEFAULT_LED_COUNT),
_brightness(DEFAULT_BRIGHTNESS),
_transitionDur(750),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
_targetFps(WLED_FPS),
_frametime(FRAMETIME_FIXED),
_cumulativeFps(2),
_isServicing(false),
_isOffRefreshRequired(false),
@ -733,7 +734,7 @@ class WS2812FX { // 96 bytes
fixInvalidSegments(),
setPixelColor(int n, uint32_t c),
show(void),
setTargetFps(uint8_t fps),
setTargetFps(uint8_t fps),
deserializeMap(uint8_t n=0);
void fill(uint32_t c) { for (int i = 0; i < _length; i++) setPixelColor(i, c); } // fill whole strip with color (inline)
@ -869,8 +870,8 @@ class WS2812FX { // 96 bytes
uint8_t _brightness;
uint16_t _transitionDur;
uint8_t _targetFps;
uint16_t _frametime;
uint8_t _targetFps;
uint16_t _frametime;
uint16_t _cumulativeFps;
// will require only 1 byte

View File

@ -196,8 +196,92 @@ void Segment::setUpLeds() {
#else
leds = &Segment::_globalLeds[start];
#endif
else if (!leds)
leds = (CRGB*)malloc(sizeof(CRGB)*length());
else if (!leds) {
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
if (psramFound())
leds = (CRGB*)ps_malloc(sizeof(CRGB)*length());
else
#endif
leds = (CRGB*)malloc(sizeof(CRGB)*length());
}
}
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
byte tcp[72];
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0;
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0;
//default palette. Differs depending on effect
if (pal == 0) switch (mode) {
case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette
case FX_MODE_COLORWAVES : pal = 26; break; // landscape 33
case FX_MODE_FILLNOISE8 : pal = 9; break; // ocean colors
case FX_MODE_NOISE16_1 : pal = 20; break; // Drywet
case FX_MODE_NOISE16_2 : pal = 43; break; // Blue cyan yellow
case FX_MODE_NOISE16_3 : pal = 35; break; // heat palette
case FX_MODE_NOISE16_4 : pal = 26; break; // landscape 33
case FX_MODE_GLITTER : pal = 11; break; // rainbow colors
case FX_MODE_SUNRISE : pal = 35; break; // heat palette
case FX_MODE_FLOW : pal = 6; break; // party
}
switch (pal) {
case 0: //default palette. Exceptions for specific effects above
targetPalette = PartyColors_p; break;
case 1: //periodically replace palette with a random one. Doesn't work with multiple FastLED segments
if (millis() - _lastPaletteChange > 5000 /*+ ((uint32_t)(255-intensity))*100*/) {
targetPalette = CRGBPalette16(
CHSV(random8(), 255, random8(128, 255)),
CHSV(random8(), 255, random8(128, 255)),
CHSV(random8(), 192, random8(128, 255)),
CHSV(random8(), 255, random8(128, 255)));
_lastPaletteChange = millis();
} break;
case 2: {//primary color only
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
targetPalette = CRGBPalette16(prim); break;}
case 3: {//primary + secondary
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
case 4: {//primary + secondary + tertiary
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
targetPalette = CRGBPalette16(ter,sec,prim); break;}
case 5: {//primary + secondary (+tert if not off), more distinct
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
if (colors[2]) {
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
} else {
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
}
break;}
case 6: //Party colors
targetPalette = PartyColors_p; break;
case 7: //Cloud colors
targetPalette = CloudColors_p; break;
case 8: //Lava colors
targetPalette = LavaColors_p; break;
case 9: //Ocean colors
targetPalette = OceanColors_p; break;
case 10: //Forest colors
targetPalette = ForestColors_p; break;
case 11: //Rainbow colors
targetPalette = RainbowColors_p; break;
case 12: //Rainbow stripe colors
targetPalette = RainbowStripeColors_p; break;
default: //progmem palettes
if (pal>245) {
targetPalette = strip.customPalettes[255-pal]; // we checked bounds above
} else {
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-13])), 72);
targetPalette.loadDynamicGradientPalette(tcp);
}
break;
}
return targetPalette;
}
void Segment::startTransition(uint16_t dur) {
@ -251,84 +335,6 @@ uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
}
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
byte tcp[72];
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0;
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0;
//default palette. Differs depending on effect
if (pal == 0) switch (mode) {
case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette
case FX_MODE_COLORWAVES : pal = 26; break; // landscape 33
case FX_MODE_FILLNOISE8 : pal = 9; break; // ocean colors
case FX_MODE_NOISE16_1 : pal = 20; break; // Drywet
case FX_MODE_NOISE16_2 : pal = 43; break; // Blue cyan yellow
case FX_MODE_NOISE16_3 : pal = 35; break; // heat palette
case FX_MODE_NOISE16_4 : pal = 26; break; // landscape 33
case FX_MODE_GLITTER : pal = 11; break; // rainbow colors
case FX_MODE_SUNRISE : pal = 35; break; // heat palette
case FX_MODE_FLOW : pal = 6; break; // party
}
switch (pal) {
case 0: //default palette. Exceptions for specific effects above
targetPalette = PartyColors_p; break;
case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments
if (millis() - _lastPaletteChange > 1000 + ((uint32_t)(255-intensity))*100) {
targetPalette = CRGBPalette16(
CHSV(random8(), 255, random8(128, 255)),
CHSV(random8(), 255, random8(128, 255)),
CHSV(random8(), 192, random8(128, 255)),
CHSV(random8(), 255, random8(128, 255)));
_lastPaletteChange = millis();
} break;}
case 2: {//primary color only
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
targetPalette = CRGBPalette16(prim); break;}
case 3: {//primary + secondary
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
case 4: {//primary + secondary + tertiary
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
targetPalette = CRGBPalette16(ter,sec,prim); break;}
case 5: {//primary + secondary (+tert if not off), more distinct
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
if (colors[2]) {
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
} else {
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
}
break;}
case 6: //Party colors
targetPalette = PartyColors_p; break;
case 7: //Cloud colors
targetPalette = CloudColors_p; break;
case 8: //Lava colors
targetPalette = LavaColors_p; break;
case 9: //Ocean colors
targetPalette = OceanColors_p; break;
case 10: //Forest colors
targetPalette = ForestColors_p; break;
case 11: //Rainbow colors
targetPalette = RainbowColors_p; break;
case 12: //Rainbow stripe colors
targetPalette = RainbowStripeColors_p; break;
default: //progmem palettes
if (pal>245) {
targetPalette = strip.customPalettes[255-pal]; // we checked bounds above
} else {
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-13])), 72);
targetPalette.loadDynamicGradientPalette(tcp);
}
break;
}
return targetPalette;
}
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
loadPalette(targetPalette, pal);
if (transitional && _t && progress() < 0xFFFFU) {
@ -400,19 +406,33 @@ uint16_t Segment::virtualHeight() const {
return vHeight;
}
uint16_t Segment::nrOfVStrips() const {
uint16_t vLen = 1;
#ifndef WLED_DISABLE_2D
if (is2D()) {
switch (map1D2D) {
case M12_pBar:
vLen = virtualWidth();
break;
}
}
#endif
return vLen;
}
// 1D strip
uint16_t Segment::virtualLength() const {
#ifndef WLED_DISABLE_2D
if (is2D()) {
uint16_t vW = virtualWidth();
uint16_t vH = virtualHeight();
uint32_t vLen = vW * vH; // use all pixels from segment
uint16_t vLen = vW * vH; // use all pixels from segment
switch (map1D2D) {
case M12_VerticalBar:
vLen = vW; // segment width since it is used in getPixelColor()
case M12_pBar:
vLen = vH;
break;
case M12_Block:
case M12_Circle:
case M12_pCorner:
case M12_pArc:
vLen = max(vW,vH); // get the longest dimension
break;
}
@ -427,6 +447,9 @@ uint16_t Segment::virtualLength() const {
void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
{
int vStrip = i>>16; // hack to allow running on virtual strips (2D segment columns/rows)
i &= 0xFFFF;
if (i >= virtualLength() || i<0) return; // if pixel would fall out of segment just exit
#ifndef WLED_DISABLE_2D
@ -438,16 +461,17 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
// use all available pixels as a long strip
setPixelColorXY(i % vW, i / vW, col);
break;
case M12_VerticalBar:
// expand 1D effect vertically
for (int y = 0; y < vH; y++) setPixelColorXY(i, y, col);
case M12_pBar:
// expand 1D effect vertically or have it play on virtual strips
if (vStrip>0) setPixelColorXY(vStrip - 1, vH - i - 1, col);
else for (int x = 0; x < vW; x++) setPixelColorXY(x, vH - i - 1, col);
break;
case M12_Circle:
case M12_pArc:
// expand in circular fashion from center
if (i==0)
setPixelColorXY(0, 0, col);
else {
float step = HALF_PI / (2*i);
float step = HALF_PI / (2.85f*i);
for (float rad = 0.0f; rad <= HALF_PI+step/2; rad += step) {
// may want to try float version as well (with or without antialiasing)
int x = roundf(sin_t(rad) * i);
@ -456,13 +480,13 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
}
}
break;
case M12_Block:
case M12_pCorner:
for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col);
for (int y = 0; y < i; y++) setPixelColorXY(i, y, col);
break;
}
return;
} else if (width()==1 || height()==1) {
} else if (strip.isMatrix && (width()==1 || height()==1)) { // TODO remove this hack
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
int x = 0, y = 0;
if (virtualHeight()>1) y = i;
@ -515,6 +539,9 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
// anti-aliased normalized version of setPixelColor()
void Segment::setPixelColor(float i, uint32_t col, bool aa)
{
int vStrip = int(i/10.0f); // hack to allow running on virtual strips (2D segment columns/rows)
i -= int(i);
if (i<0.0f || i>1.0f) return; // not normalized
float fC = i * (virtualLength()-1);
@ -523,26 +550,29 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
uint16_t iR = roundf(fC+0.49f);
float dL = fC - iL;
float dR = iR - fC;
uint32_t cIL = getPixelColor(iL);
uint32_t cIR = getPixelColor(iR);
uint32_t cIL = getPixelColor(iL | (vStrip<<16));
uint32_t cIR = getPixelColor(iR | (vStrip<<16));
if (iR!=iL) {
// blend L pixel
cIL = color_blend(col, cIL, uint8_t(dL*255.0f));
setPixelColor(iL, cIL);
setPixelColor(iL | (vStrip<<16), cIL);
// blend R pixel
cIR = color_blend(col, cIR, uint8_t(dR*255.0f));
setPixelColor(iR, cIR);
setPixelColor(iR | (vStrip<<16), cIR);
} else {
// exact match (x & y land on a pixel)
setPixelColor(iL, col);
setPixelColor(iL | (vStrip<<16), col);
}
} else {
setPixelColor(uint16_t(roundf(fC)), col);
setPixelColor(uint16_t(roundf(fC)) | (vStrip<<16), col);
}
}
uint32_t Segment::getPixelColor(uint16_t i)
uint32_t Segment::getPixelColor(int i)
{
int vStrip = i>>16;
i &= 0xFFFF;
#ifndef WLED_DISABLE_2D
if (is2D()) { // if this does not work use strip.isMatrix
uint16_t vH = virtualHeight(); // segment height in logical pixels
@ -551,11 +581,12 @@ uint32_t Segment::getPixelColor(uint16_t i)
case M12_Pixels:
return getPixelColorXY(i % vW, i / vW);
break;
case M12_VerticalBar:
return getPixelColorXY(i, 0);
case M12_pBar:
if (vStrip>0) return getPixelColorXY(vStrip - 1, vH - i -1);
else return getPixelColorXY(0, vH - i -1);
break;
case M12_Circle:
case M12_Block:
case M12_pArc:
case M12_pCorner:
// use longest dimension
return vW>vH ? getPixelColorXY(i, 0) : getPixelColorXY(0, i);
break;
@ -1079,8 +1110,8 @@ uint16_t WS2812FX::getFps() {
}
void WS2812FX::setTargetFps(uint8_t fps) {
if (fps > 0 && fps <= 120) _targetFps = fps;
_frametime = 1000 / _targetFps;
if (fps > 0 && fps <= 120) _targetFps = fps;
_frametime = 1000 / _targetFps;
}
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
@ -1127,7 +1158,7 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
// would be dangerous if applied immediately (could exceed ABL), but will not output until the next show()
busses.setBrightness(b);
} else {
unsigned long t = millis();
unsigned long t = millis();
if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon
}
}
@ -1180,7 +1211,7 @@ uint16_t WS2812FX::getLengthPhysical(void) {
//returns if there is an RGBW bus (supports RGB and White, not only white)
//not influenced by auto-white mode, also true if white slider does not affect output white channel
bool WS2812FX::hasRGBWBus(void) {
for (size_t b = 0; b < busses.getNumBusses(); b++) {
for (size_t b = 0; b < busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) {
@ -1190,12 +1221,12 @@ bool WS2812FX::hasRGBWBus(void) {
return true;
}
}
return false;
return false;
}
bool WS2812FX::hasCCTBus(void) {
if (cctFromRgb && !correctWB) return false;
for (size_t b = 0; b < busses.getNumBusses(); b++) {
if (cctFromRgb && !correctWB) return false;
for (size_t b = 0; b < busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) {
@ -1204,7 +1235,7 @@ bool WS2812FX::hasCCTBus(void) {
return true;
}
}
return false;
return false;
}
void WS2812FX::purgeSegments(bool force) {
@ -1237,8 +1268,8 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
boundsUnchanged &= (seg.startY == startY && seg.stopY == stopY);
}
if (boundsUnchanged
&& (!grouping || (seg.grouping == grouping && seg.spacing == spacing))
&& (offset == UINT16_MAX || offset == seg.offset)) return;
&& (!grouping || (seg.grouping == grouping && seg.spacing == spacing))
&& (offset == UINT16_MAX || offset == seg.offset)) return;
//if (seg.stop) setRange(seg.start, seg.stop -1, BLACK); //turn old segment range off
if (seg.stop) seg.fill(BLACK); //turn old segment range off
@ -1273,7 +1304,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
seg.grouping = grouping;
seg.spacing = spacing;
}
if (offset < UINT16_MAX) seg.offset = offset;
if (offset < UINT16_MAX) seg.offset = offset;
seg.markForReset();
if (!boundsUnchanged) seg.refreshLightCapabilities();
}
@ -1408,7 +1439,7 @@ void WS2812FX::setTransitionMode(bool t)
void WS2812FX::printSize()
{
size_t size = 0;
for (const Segment seg : _segments) size += seg.getSize();
for (const Segment &seg : _segments) size += seg.getSize();
DEBUG_PRINTF("Segments: %d -> %uB\n", _segments.size(), size);
DEBUG_PRINTF("Modes: %d*%d=%uB\n", sizeof(mode_ptr), _mode.size(), (_mode.capacity()*sizeof(mode_ptr)));
DEBUG_PRINTF("Data: %d*%d=%uB\n", sizeof(const char *), _modeData.size(), (_modeData.capacity()*sizeof(const char *)));

View File

@ -283,11 +283,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
JsonArray hw_if_spi = hw[F("if")][F("spi-pin")];
CJSON(spi_mosi, hw_if_spi[0]);
CJSON(spi_sclk, hw_if_spi[1]);
PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_sclk, true } };
if (spi_mosi >= 0 && spi_sclk >= 0 && pinManager.allocateMultiplePins(spi, 2, PinOwner::HW_SPI)) {
CJSON(spi_miso, hw_if_spi[2]);
PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_miso, true }, { spi_sclk, true } };
if (spi_mosi >= 0 && spi_sclk >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
// do not initialise bus here
} else {
spi_mosi = -1;
spi_miso = -1;
spi_sclk = -1;
}
@ -746,6 +748,7 @@ void serializeConfig() {
JsonArray hw_if_spi = hw_if.createNestedArray("spi-pin");
hw_if_spi.add(spi_mosi);
hw_if_spi.add(spi_sclk);
hw_if_spi.add(spi_miso);
//JsonObject hw_status = hw.createNestedObject("status");
//hw_status["pin"] = -1;

View File

@ -384,6 +384,9 @@
#if defined(ESP8266) && defined(HW_PIN_DATASPI)
#undef HW_PIN_DATASPI
#endif
#if defined(ESP8266) && defined(HW_PIN_MISOSPI)
#undef HW_PIN_MISOSPI
#endif
#if defined(ESP8266) && defined(HW_PIN_CSSPI)
#undef HW_PIN_CSSPI
#endif
@ -394,6 +397,9 @@
#ifndef HW_PIN_DATASPI
#define HW_PIN_DATASPI MOSI
#endif
#ifndef HW_PIN_MISOSPI
#define HW_PIN_MISOSPI MISO
#endif
#ifndef HW_PIN_CSSPI
#define HW_PIN_CSSPI SS
#endif

View File

@ -1219,6 +1219,12 @@ TD .checkmark, TD .radiomark {
filter: grayscale(100%);
}
.lbl-l {
font-size: 13px;
text-align: center;
padding: 4px 0;
}
.lbl-s {
display: inline-block;
/* margin: 10px 4px 0 0; */

View File

@ -574,7 +574,7 @@ function populatePresets(fromls)
<i class="icons e-icon flr" id="sege${i+100}" onclick="expand(${i+100})">&#xe395;</i>
<div class="presin lstIcontent" id="seg${i+100}"></div>
</div>`;
pNum++;
pNum++;
}
gId('pcont').innerHTML = cn;
@ -643,7 +643,7 @@ function populateInfo(i)
var pwru = "Not calculated";
if (pwr > 1000) {pwr /= 1000; pwr = pwr.toFixed((pwr > 10) ? 0 : 1); pwru = pwr + " A";}
else if (pwr > 0) {pwr = 50 * Math.round(pwr/50); pwru = pwr + " mA";}
var urows="";
var urows="";
if (i.u) {
for (const [k, val] of Object.entries(i.u)) {
if (val[1])
@ -714,7 +714,7 @@ function populateSegments(s)
}
let map2D = `<div id="seg${i}map2D" data-map="map2D" class="lbl-s hide">Expand 1D FX<br>
<div class="sel-p"><select class="sel-p" id="seg${i}mp12" onchange="setMp12(${i})">
<option value="0" ${inst.mp12==0?' selected':''}>None</option>
<option value="0" ${inst.mp12==0?' selected':''}>Strip</option>
<option value="1" ${inst.mp12==1?' selected':''}>Bar</option>
<option value="2" ${inst.mp12==2?' selected':''}>Arc</option>
<option value="3" ${inst.mp12==3?' selected':''}>Corner</option>
@ -774,7 +774,7 @@ function populateSegments(s)
${!isM?rvXck:''}
${isM&&stoY-staY>1&&stoX-staX>1?map2D:''}
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim}
<label class="check revchkl">
<label class="check revchkl" id="seg${i}lbtm">
${isM?'Transpose':'Mirror effect'}
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
<span class="checkmark"></span>
@ -863,10 +863,10 @@ function populatePalettes()
html += generateListItemHtml(
'palette',
pa[0],
pa[1],
'setPalette',
pa[1],
'setPalette',
`<div class="lstIprev" style="${genPalPrevCss(pa[0])}"></div>`
);
);
}
gId('pallist').innerHTML=html;
@ -932,7 +932,7 @@ function genPalPrevCss(id)
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', effectPar = '')
{
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" ${effectPar===''?'':'data-opt="'+effectPar+'"'}onClick="${clickAction}(${id})">
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" ${effectPar===''?'':'data-opt="'+effectPar+'"'}onClick="${clickAction}(${id})">
<label class="radio schkl" onclick="event.preventDefault()">
<input type="radio" value="${id}" name="${listName}">
<span class="radiomark"></span>
@ -1035,19 +1035,27 @@ function updateLen(s)
var stop = parseInt(gId(`seg${s}e`).value);
var len = stop - (cfg.comp.seglen?0:start);
if (isM) {
// matrix setup
let startY = parseInt(gId(`seg${s}sY`).value);
let stopY = parseInt(gId(`seg${s}eY`).value);
len *= (stopY-(cfg.comp.seglen?0:startY));
let tPL = gId(`seg${s}lbtm`);
if (stop-start>1 && stopY-startY>1) {
// 2D segment
tPL.classList.remove("hide"); // unhide transpose checkbox
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
if (sE) {
let sN = sE.querySelector(".lstIname").innerText;
let seg = gId(`seg${s}map2D`);
if (seg) {
if (sN.indexOf("\u25A6")<0) seg.classList.remove("hide");
else seg.classList.add("hide");
if(sN.indexOf("\u25A6")<0) seg.classList.remove("hide"); // unhide mapping for 1D effects (| in name)
else seg.classList.add("hide"); // hide mapping otherwise
}
}
} else {
// 1D segment in 2D set-up
tPL.classList.add("hide"); // hide transpose checkbox
gId(`seg${s}tp`).checked = false; // and uncheck it
}
}
var out = "(delete)";
@ -1245,7 +1253,7 @@ function readState(s,command=false)
tr = s.transition;
gId('tt').value = tr/10;
populateSegments(s);
var selc=0;
var sellvl=0; // 0: selc is invalid, 1: selc is mainseg, 2: selc is first selected
@ -1277,7 +1285,7 @@ function readState(s,command=false)
updateUI();
return true;
}
var cd = gId('csl').children;
for (let e = cd.length-1; e >= 0; e--) {
cd[e].dataset.r = i.col[e][0];
@ -1348,13 +1356,13 @@ function readState(s,command=false)
function setEffectParameters(idx)
{
if (!(Array.isArray(fxdata) && fxdata.length>idx)) return;
var controlDefined = (fxdata[idx].substr(0,1) == "@");
var controlDefined = (fxdata[idx].substr(0,1) == "@");
var effectPar = fxdata[idx].substr(1);
var effectPars = (effectPar == '')?[]:effectPar.split(";");
var slOnOff = (effectPars.length==0 || effectPars[0]=='')?[]:effectPars[0].split(",");
var coOnOff = (effectPars.length<2 || effectPars[1]=='')?[]:effectPars[1].split(",");
var paOnOff = (effectPars.length<3 || effectPars[2]=='')?[]:effectPars[2].split(",");
// set html slider items on/off
//var nSliders = Math.min(7,Math.floor(gId("sliders").children.length)); // div for each slider + filter + options
let nSliders = 5;
@ -1434,7 +1442,7 @@ function setEffectParameters(idx)
}
}
gId("cslLabel").innerHTML = cslLabel;
// set palette on/off
var palw = gId("palw"); // wrapper
var pall = gId("pall"); // label
@ -1580,28 +1588,28 @@ function toggleSync()
function toggleLiveview()
{
//WLEDSR adding liveview2D support
if (isInfo && isM) toggleInfo();
if (isNodes && isM) toggleNodes();
isLv = !isLv;
//WLEDSR adding liveview2D support
if (isInfo && isM) toggleInfo();
if (isNodes && isM) toggleNodes();
isLv = !isLv;
var lvID = "liveview";
if (isM) {
lvID = "liveview2D"
if (isLv) {
var cn = '<iframe id="liveview2D" src="about:blank"></iframe>';
d.getElementById('kliveview2D').innerHTML = cn;
var lvID = "liveview";
if (isM) {
lvID = "liveview2D"
if (isLv) {
var cn = '<iframe id="liveview2D" src="about:blank"></iframe>';
d.getElementById('kliveview2D').innerHTML = cn;
}
gId('mliveview2D').style.transform = (isLv) ? "translateY(0px)":"translateY(100%)";
}
gId('mliveview2D').style.transform = (isLv) ? "translateY(0px)":"translateY(100%)";
}
gId(lvID).style.display = (isLv) ? "block":"none";
var url = (loc?`http://${locip}`:'') + "/" + lvID;
gId(lvID).src = (isLv) ? url:"about:blank";
gId('buttonSr').className = (isLv) ? "active":"";
if (!isLv && ws && ws.readyState === WebSocket.OPEN) ws.send('{"lv":false}');
size();
gId(lvID).style.display = (isLv) ? "block":"none";
var url = (loc?`http://${locip}`:'') + "/" + lvID;
gId(lvID).src = (isLv) ? url:"about:blank";
gId('buttonSr').className = (isLv) ? "active":"";
if (!isLv && ws && ws.readyState === WebSocket.OPEN) ws.send('{"lv":false}');
size();
}
function toggleInfo()
@ -1806,9 +1814,9 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
<span class="checkmark"></span>
</label>`;
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>0) {
content += `<div class="sel">Ledmap:&nbsp;<select class="sel-p" id="p${i}lmp"><option value="">None</option>`;
content += `<div class="lbl-l">Ledmap:&nbsp;<div class="sel-p"><select class="sel-p" id="p${i}lmp"><option value="">None</option>`;
for (const k of (lastinfo.maps||[])) content += `<option value="${k}"${(i>0 && pJson[i].ledmap==k)?" selected":""}>${k}</option>`;
content += "</select></div>";
content += "</select></div></div>";
}
}
@ -1820,17 +1828,12 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
<span class="lstIname">
${pl?"Show playlist editor":(i>0)?"Overwrite with state":"Use current state"}
</span>
<input type="checkbox" id="p${i}cstgl" onchange="tglCs(${i})" ${(i==0||pl)?"checked":""}>
<span class="checkmark"></span>
</label>
</div>
<div class="po2" id="p${i}o2">
API command<br>
<textarea class="apitxt" id="p${i}api"></textarea>
</div>
<div class="po1" id="p${i}o1">
${content}
<input type="checkbox" id="p${i}cstgl" onchange="tglCs(${i})" ${(i==0||pl)?"checked":""}>
<span class="checkmark"></span>
</label>
</div>
<div class="po2" id="p${i}o2">API command<br><textarea class="apitxt" id="p${i}api"></textarea></div>
<div class="po1" id="p${i}o1">${content}</div>
<div class="c">Save to ID <input class="noslide" id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
<div class="c">
<button class="btn btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon">&#xe390;</i>Save</button>
@ -1846,6 +1849,10 @@ function makePUtil()
p.classList.remove('staybot');
p.classList.add('pres');
p.innerHTML = `<div class="presin expanded">${makeP(0)}</div>`;
let pTx = gId('p0txt');
pTx.focus();
pTx.value = eJson.find((o)=>{return o.id==selectedFx}).name;
pTx.select();
p.scrollIntoView({
behavior: 'smooth',
block: 'center'
@ -1853,9 +1860,10 @@ function makePUtil()
gId('psFind').classList.remove('staytop');
}
function makePlEntry(p,i) {
return `<div class="plentry">
<div class="hrz"></div>
function makePlEntry(p,i)
{
return `<div class="plentry">
<div class="hrz"></div>
<table>
<tr>
<td width="80%" colspan=2>
@ -1889,6 +1897,7 @@ function makePlUtil()
p.classList.remove('staybot');
p.innerHTML = `<div class="pres"><div class="segin expanded" id="seg100">${makeP(0,true)}</div></div>`;
refreshPlE(0);
gId('p0txt').focus();
p.scrollIntoView({
behavior: 'smooth',
block: 'center'
@ -1916,7 +1925,11 @@ function tglCs(i)
function tglSegn(s)
{
let t = gId(s<100?`seg${s}t`:`p${s-100}txt`);
if (t) t.classList.toggle("show");
if (t) {
t.classList.toggle("show");
t.focus();
t.select();
}
event.preventDefault();
event.stopPropagation();
}
@ -1982,6 +1995,7 @@ function setSeg(s)
var stopY = parseInt(gId(`seg${s}eY`).value);
obj.seg.startY = startY;
obj.seg.stopY = (cfg.comp.seglen?startY:0)+stopY;
obj.seg.tp = gId(`seg${s}tp`).checked;
}
if (gId(`seg${s}grp`)) {
var grp = parseInt(gId(`seg${s}grp`).value);
@ -2184,7 +2198,7 @@ function saveP(i,pl)
gId(`p${i}warn`).innerHTML = "&#9888; Syntax error in custom JSON API command";
return;
} else if (raw.indexOf("Please") == 0) {
gId(`p${i}warn`).innerHTML = "&#9888; Please refresh the page before modifying this preset";
gId(`p${i}warn`).innerHTML = "&#9888; Please refresh the page before modifying this preset";
return;
}
}

View File

@ -41,7 +41,7 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
#endif
// Autogenerated from wled00/data/update.htm, do not edit!!
const uint16_t PAGE_update_length = 616;
const uint16_t PAGE_update_length = 615;
const uint8_t PAGE_update[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x75, 0x53, 0x5d, 0x6f, 0xd4, 0x30,
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x71, 0x4e, 0x41, 0xbc, 0x50, 0x92, 0x14, 0x8e,
@ -66,22 +66,22 @@ const uint8_t PAGE_update[] PROGMEM = {
0xe9, 0xc1, 0x32, 0x20, 0xe5, 0x0e, 0x03, 0x99, 0xd2, 0x8f, 0x16, 0xcd, 0x20, 0x03, 0xe6, 0x53,
0xff, 0x8a, 0x60, 0x92, 0xd3, 0xcd, 0x71, 0xac, 0x7b, 0x43, 0x6e, 0x3e, 0x4c, 0x17, 0xdf, 0xb8,
0x88, 0xd2, 0x5a, 0xd0, 0x6c, 0x07, 0x21, 0x12, 0xe3, 0x05, 0x2b, 0xe2, 0x20, 0x1d, 0xcb, 0x94,
0x95, 0x31, 0x96, 0x3c, 0x9a, 0x81, 0x57, 0xe7, 0xe2, 0xe5, 0x6b, 0x71, 0xbe, 0xaa, 0xed, 0x39,
0x6d, 0x43, 0x55, 0xda, 0x22, 0x54, 0x57, 0x7e, 0x9f, 0xb6, 0x60, 0xd8, 0x01, 0xb3, 0x34, 0x43,
0x44, 0x56, 0x1b, 0x27, 0xc3, 0x81, 0x38, 0x24, 0xcb, 0xba, 0x00, 0x4d, 0xc9, 0x3b, 0xc4, 0x21,
0x5e, 0xe4, 0x79, 0x6b, 0xb0, 0x1b, 0x6b, 0xa1, 0x7c, 0x9f, 0xbf, 0x37, 0x41, 0x79, 0xef, 0xb7,
0x06, 0xf2, 0x69, 0xe5, 0x3c, 0x80, 0x05, 0x19, 0x21, 0x72, 0x86, 0x32, 0x90, 0x5f, 0x25, 0xff,
0x56, 0x5b, 0xe9, 0xb6, 0x24, 0x8b, 0xe9, 0x5b, 0x96, 0x25, 0x13, 0x4e, 0x3c, 0xf4, 0x45, 0xc4,
0xce, 0x80, 0xd5, 0x51, 0x18, 0x7f, 0xa4, 0x3d, 0x51, 0xfc, 0x49, 0x2d, 0xe2, 0xae, 0xbd, 0x4c,
0xf2, 0x97, 0x0d, 0x4d, 0xb8, 0x8a, 0x8f, 0x23, 0x49, 0x3b, 0x85, 0x34, 0x97, 0x69, 0x87, 0xc2,
0xb8, 0x61, 0x44, 0x36, 0xeb, 0xd5, 0x18, 0x0b, 0xa7, 0x40, 0x9f, 0x54, 0x0d, 0xf0, 0x38, 0x9a,
0x00, 0x7a, 0x46, 0xd7, 0x23, 0x22, 0x65, 0x72, 0x86, 0xcf, 0x3a, 0x12, 0xd9, 0xec, 0xd4, 0x59,
0x91, 0xcf, 0xe5, 0x7f, 0x40, 0xe7, 0xc3, 0x24, 0xbe, 0xb2, 0x46, 0x6d, 0x4b, 0xbe, 0x9e, 0xb4,
0x5f, 0x53, 0xd4, 0x7f, 0x35, 0x25, 0x93, 0xaa, 0x42, 0x9b, 0x5d, 0x96, 0xbc, 0x9c, 0x82, 0x4a,
0x34, 0x55, 0x62, 0xa7, 0xf4, 0x09, 0x21, 0x08, 0x9c, 0xc8, 0x37, 0x69, 0x59, 0xa6, 0x3d, 0x73,
0x1e, 0x99, 0xb2, 0x9e, 0x0e, 0x3e, 0xd0, 0xac, 0x4d, 0x80, 0xd8, 0x25, 0x3f, 0x06, 0xd9, 0x02,
0xbb, 0x58, 0x16, 0x39, 0xf1, 0x4d, 0xeb, 0x4e, 0xa9, 0x9b, 0x22, 0x38, 0xfd, 0xdb, 0x3f, 0x01,
0xce, 0x0e, 0xa3, 0x73, 0xf1, 0x03, 0x00, 0x00
0x95, 0x31, 0x96, 0x3c, 0x9a, 0x81, 0x57, 0xe7, 0xe2, 0xe5, 0x6b, 0x71, 0xbe, 0xaa, 0xcf, 0x69,
0x19, 0x2a, 0xd2, 0x12, 0xa1, 0xba, 0xf2, 0xfb, 0xb4, 0x04, 0xc3, 0x0e, 0x98, 0xa5, 0x11, 0x22,
0xb2, 0xda, 0x38, 0x19, 0x0e, 0x44, 0x21, 0x59, 0xd6, 0x05, 0x68, 0x4a, 0xde, 0x21, 0x0e, 0xf1,
0x22, 0xcf, 0x5b, 0x83, 0xdd, 0x58, 0x0b, 0xe5, 0xfb, 0xfc, 0xbd, 0x09, 0xca, 0x7b, 0xbf, 0x35,
0x90, 0x4f, 0x1b, 0xe7, 0x01, 0x2c, 0xc8, 0x08, 0x91, 0x33, 0x94, 0x81, 0xec, 0x2a, 0xf9, 0xb7,
0xda, 0x4a, 0xb7, 0x25, 0x55, 0x4c, 0xdf, 0xb2, 0x2c, 0x79, 0x70, 0xe2, 0xa1, 0x2f, 0x22, 0x76,
0x06, 0xac, 0x8e, 0xc2, 0xf8, 0x23, 0xed, 0x89, 0xe2, 0x4f, 0x6a, 0x11, 0x77, 0xed, 0x65, 0x52,
0xbf, 0x6c, 0x68, 0xc2, 0x55, 0x7c, 0x1c, 0x49, 0xd9, 0x29, 0xa3, 0xb9, 0x4c, 0x3b, 0x14, 0xc6,
0x0d, 0x23, 0xb2, 0x59, 0xae, 0xc6, 0x58, 0x38, 0xe5, 0xf9, 0x24, 0x6a, 0x80, 0xc7, 0xd1, 0x04,
0xd0, 0x33, 0xba, 0x1e, 0x11, 0x29, 0x92, 0x33, 0x7c, 0x96, 0x91, 0xc8, 0x66, 0xa3, 0xce, 0x8a,
0x7c, 0x2e, 0xff, 0x03, 0x3a, 0x1f, 0x26, 0xed, 0x95, 0x35, 0x6a, 0x5b, 0xf2, 0xf5, 0x24, 0xfd,
0x9a, 0x92, 0xfe, 0xab, 0x29, 0x79, 0x54, 0x15, 0xda, 0xec, 0xb2, 0x64, 0xe5, 0x94, 0x53, 0xa2,
0xa9, 0x12, 0x3b, 0x85, 0x4f, 0x08, 0x41, 0xe0, 0x44, 0xbe, 0x49, 0xcb, 0x32, 0xed, 0x99, 0xf3,
0xc8, 0x94, 0xf5, 0x74, 0xf0, 0x81, 0x66, 0x6d, 0x02, 0xc4, 0x2e, 0xf9, 0x31, 0xc8, 0x16, 0xd8,
0xc5, 0xb2, 0xc8, 0x89, 0x6f, 0x5a, 0x77, 0x0a, 0xdd, 0x94, 0xc0, 0xe9, 0xd7, 0xfe, 0x09, 0x43,
0x44, 0x4f, 0x48, 0xf0, 0x03, 0x00, 0x00
};

View File

@ -8,7 +8,7 @@
// Autogenerated from wled00/data/style.css, do not edit!!
const uint16_t PAGE_settingsCss_length = 824;
const uint8_t PAGE_settingsCss[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xad, 0x55, 0x5d, 0x8b, 0x9c, 0x30,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x55, 0x5d, 0x8b, 0x9c, 0x30,
0x14, 0xfd, 0x2b, 0x96, 0x61, 0x61, 0x0b, 0xa3, 0xa8, 0xa3, 0xb3, 0xd3, 0x48, 0xa1, 0xf4, 0xbd,
0x6f, 0xa5, 0x14, 0xca, 0x3e, 0x44, 0x73, 0x1d, 0xc3, 0xe4, 0x43, 0x92, 0xd8, 0x75, 0x2a, 0xfe,
0xf7, 0x26, 0x7e, 0xac, 0xce, 0xac, 0x6c, 0x5f, 0xca, 0xe0, 0xa0, 0xde, 0x98, 0x7b, 0xee, 0xb9,
@ -66,7 +66,7 @@ const uint8_t PAGE_settingsCss[] PROGMEM = {
// Autogenerated from wled00/data/settings.htm, do not edit!!
const uint16_t PAGE_settings_length = 985;
const uint8_t PAGE_settings[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xad, 0x56, 0x6d, 0x6f, 0xdb, 0x36,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x56, 0x6d, 0x6f, 0xdb, 0x36,
0x10, 0xfe, 0xee, 0x5f, 0xc1, 0xb0, 0x58, 0x23, 0xa1, 0xb2, 0xec, 0x38, 0xc3, 0xb0, 0xc9, 0x96,
0x8b, 0x35, 0x2f, 0x9d, 0x87, 0x04, 0x0d, 0x90, 0xa4, 0xdd, 0x80, 0x7d, 0xa1, 0xc9, 0x93, 0xcc,
0x46, 0x22, 0x05, 0xf2, 0xe4, 0xc4, 0x73, 0xf3, 0xdf, 0x77, 0x94, 0x9d, 0xb7, 0x36, 0xd8, 0x8a,
@ -134,7 +134,7 @@ const uint8_t PAGE_settings[] PROGMEM = {
// Autogenerated from wled00/data/settings_wifi.htm, do not edit!!
const uint16_t PAGE_settings_wifi_length = 1557;
const uint8_t PAGE_settings_wifi[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xad, 0x57, 0xff, 0x4f, 0xdb, 0x38,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x57, 0xff, 0x4f, 0xdb, 0x38,
0x14, 0xff, 0x3d, 0x7f, 0x85, 0xf1, 0x49, 0x53, 0xa3, 0x85, 0x94, 0xb6, 0xc7, 0x6e, 0x62, 0x49,
0x76, 0x5d, 0xdb, 0x0d, 0xee, 0x18, 0xeb, 0x29, 0x68, 0xe8, 0xa4, 0x93, 0x26, 0x37, 0x79, 0x6d,
0x3d, 0x9c, 0x38, 0x17, 0x3b, 0x2d, 0x88, 0xf1, 0xbf, 0xdf, 0xb3, 0x93, 0x96, 0x16, 0xe8, 0x36,
@ -238,7 +238,7 @@ const uint8_t PAGE_settings_wifi[] PROGMEM = {
// Autogenerated from wled00/data/settings_leds.htm, do not edit!!
const uint16_t PAGE_settings_leds_length = 7357;
const uint8_t PAGE_settings_leds[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xdd, 0x3c, 0xed, 0x76, 0xe2, 0xc6,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xdd, 0x3c, 0xed, 0x76, 0xe2, 0xc6,
0x92, 0xff, 0x79, 0x8a, 0x76, 0x27, 0x71, 0xa4, 0x8b, 0x0c, 0x12, 0x1f, 0x8e, 0x07, 0x10, 0xac,
0xb1, 0x3d, 0x13, 0xdf, 0x6b, 0xc7, 0x3e, 0xc6, 0xc9, 0xdc, 0x3d, 0x93, 0x39, 0x19, 0x21, 0x1a,
0xd0, 0x58, 0x48, 0xba, 0x92, 0xb0, 0x87, 0xb5, 0xd9, 0x67, 0xda, 0x67, 0xd8, 0x27, 0xdb, 0xaa,
@ -704,7 +704,7 @@ const uint8_t PAGE_settings_leds[] PROGMEM = {
// Autogenerated from wled00/data/settings_dmx.htm, do not edit!!
const uint16_t PAGE_settings_dmx_length = 1612;
const uint8_t PAGE_settings_dmx[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x95, 0x57, 0xdb, 0x72, 0xdb, 0x36,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x57, 0xdb, 0x72, 0xdb, 0x36,
0x10, 0x7d, 0xd7, 0x57, 0x20, 0x78, 0x88, 0xc9, 0x31, 0x43, 0x4a, 0x4e, 0x95, 0x36, 0x32, 0x49,
0x37, 0x56, 0x5c, 0xdb, 0x1d, 0xdb, 0xf5, 0x44, 0x49, 0xd3, 0x4e, 0xd3, 0xe9, 0x40, 0xe4, 0x4a,
0x44, 0x4c, 0x02, 0x2c, 0x00, 0x4a, 0x76, 0x2e, 0xff, 0xde, 0x05, 0x48, 0x5d, 0xec, 0xd8, 0x69,
@ -811,7 +811,7 @@ const uint8_t PAGE_settings_dmx[] PROGMEM = {
// Autogenerated from wled00/data/settings_ui.htm, do not edit!!
const uint16_t PAGE_settings_ui_length = 3090;
const uint8_t PAGE_settings_ui[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xad, 0x59, 0x6b, 0x73, 0xda, 0x48,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x59, 0x6b, 0x73, 0xda, 0x48,
0x16, 0xfd, 0xce, 0xaf, 0xe8, 0x74, 0x52, 0x1e, 0x54, 0x56, 0x04, 0x4e, 0x66, 0x6b, 0x13, 0x40,
0x78, 0x63, 0xc7, 0x93, 0x78, 0xca, 0xd9, 0x64, 0x83, 0xbd, 0x99, 0xad, 0xac, 0xcb, 0x23, 0xa4,
0x06, 0x3a, 0x16, 0x92, 0x46, 0xdd, 0x32, 0x66, 0x09, 0xff, 0x7d, 0xcf, 0xed, 0x96, 0x40, 0x60,
@ -1011,7 +1011,7 @@ const uint8_t PAGE_settings_ui[] PROGMEM = {
// Autogenerated from wled00/data/settings_sync.htm, do not edit!!
const uint16_t PAGE_settings_sync_length = 3153;
const uint8_t PAGE_settings_sync[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x9d, 0x5a, 0x6d, 0x77, 0xda, 0xb8,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x9d, 0x5a, 0x6d, 0x77, 0xda, 0xb8,
0x12, 0xfe, 0xee, 0x5f, 0xa1, 0xf8, 0xc3, 0x2e, 0x6c, 0x08, 0x18, 0x12, 0xd2, 0x94, 0x62, 0xf7,
0x86, 0x90, 0x26, 0xec, 0x36, 0x0d, 0x85, 0x64, 0x5f, 0xce, 0xb9, 0xe7, 0xec, 0x11, 0xb6, 0x00,
0x25, 0xb6, 0xe5, 0xb5, 0xe5, 0xbc, 0x9c, 0x6e, 0xff, 0xfb, 0x9d, 0x91, 0x6c, 0x03, 0x06, 0x02,
@ -1215,7 +1215,7 @@ const uint8_t PAGE_settings_sync[] PROGMEM = {
// Autogenerated from wled00/data/settings_time.htm, do not edit!!
const uint16_t PAGE_settings_time_length = 3302;
const uint8_t PAGE_settings_time[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xd5, 0x1a, 0x6b, 0x57, 0xdb, 0x3a,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xd5, 0x1a, 0x6b, 0x57, 0xdb, 0x3a,
0xf2, 0x7b, 0x7e, 0x85, 0x50, 0x7b, 0xb8, 0xf1, 0xc5, 0x79, 0x42, 0x5a, 0x48, 0x62, 0x77, 0x43,
0x48, 0x0b, 0x2d, 0x09, 0x9c, 0x26, 0xbd, 0xec, 0xf6, 0x71, 0x6e, 0x15, 0x5b, 0x49, 0x0c, 0x8e,
0xe4, 0xb5, 0x65, 0x02, 0x4b, 0xf9, 0xef, 0x3b, 0x92, 0x1c, 0xe7, 0x85, 0x81, 0xf6, 0xde, 0xfd,
@ -1428,7 +1428,7 @@ const uint8_t PAGE_settings_time[] PROGMEM = {
// Autogenerated from wled00/data/settings_sec.htm, do not edit!!
const uint16_t PAGE_settings_sec_length = 2405;
const uint8_t PAGE_settings_sec[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xa5, 0x58, 0x6d, 0x53, 0xdb, 0x48,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xa5, 0x58, 0x6d, 0x53, 0xdb, 0x48,
0x12, 0xfe, 0xee, 0x5f, 0x31, 0x4c, 0xaa, 0x58, 0xeb, 0x22, 0x2c, 0x43, 0x72, 0x5b, 0x09, 0x20,
0xe7, 0x20, 0x90, 0x0d, 0x57, 0x10, 0x28, 0x6c, 0x36, 0x77, 0x95, 0x4b, 0xa5, 0xc6, 0xd2, 0xd8,
0x9a, 0x58, 0xd6, 0x68, 0x67, 0x46, 0x38, 0xbe, 0xec, 0xfe, 0xf7, 0x7b, 0x7a, 0x24, 0xd9, 0x86,
@ -1585,7 +1585,7 @@ const uint8_t PAGE_settings_sec[] PROGMEM = {
// Autogenerated from wled00/data/settings_um.htm, do not edit!!
const uint16_t PAGE_settings_um_length = 2514;
const uint8_t PAGE_settings_um[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xdd, 0x58, 0xdb, 0x72, 0xdb, 0x38,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xdd, 0x58, 0xdb, 0x72, 0xdb, 0x38,
0x12, 0x7d, 0xd7, 0x57, 0xd0, 0x88, 0xcb, 0x26, 0x4b, 0x34, 0x25, 0xc7, 0x3b, 0xb3, 0x89, 0x24,
0xc8, 0x93, 0x38, 0xc9, 0x44, 0x9b, 0x8b, 0x5d, 0xa5, 0xb9, 0xd4, 0x96, 0xd7, 0x35, 0xa6, 0x44,
0x48, 0x42, 0x4c, 0x81, 0x5c, 0x00, 0xf4, 0x65, 0x65, 0xfd, 0xfb, 0x9e, 0x06, 0x49, 0x5d, 0x1c,
@ -1749,7 +1749,7 @@ const uint8_t PAGE_settings_um[] PROGMEM = {
// Autogenerated from wled00/data/settings_2D.htm, do not edit!!
const uint16_t PAGE_settings_2D_length = 1754;
const uint8_t PAGE_settings_2D[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x8d, 0x58, 0x6d, 0x73, 0xdb, 0x36,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x8d, 0x58, 0x6d, 0x73, 0xdb, 0x36,
0x12, 0xfe, 0xce, 0x5f, 0x01, 0x63, 0x3a, 0x2d, 0xd9, 0x50, 0x94, 0xe4, 0xde, 0x75, 0x3a, 0x16,
0x49, 0x37, 0x6e, 0xdc, 0xda, 0x1d, 0x7b, 0xe2, 0x89, 0x72, 0xce, 0xdc, 0x5c, 0x3a, 0x29, 0x44,
0xae, 0x44, 0xc4, 0x24, 0xc0, 0x01, 0x20, 0xd9, 0xae, 0xe2, 0xff, 0x7e, 0x0b, 0x90, 0x12, 0x25,
@ -1865,7 +1865,7 @@ const uint8_t PAGE_settings_2D[] PROGMEM = {
// Autogenerated from wled00/data/settings_pin.htm, do not edit!!
const uint16_t PAGE_settings_pin_length = 471;
const uint8_t PAGE_settings_pin[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x5d, 0x52, 0x4d, 0x6f, 0x13, 0x31,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x5d, 0x52, 0x4d, 0x6f, 0x13, 0x31,
0x10, 0xbd, 0xef, 0xaf, 0x30, 0x73, 0x69, 0x82, 0x92, 0x6c, 0xa8, 0xa8, 0x04, 0xaa, 0xbd, 0x42,
0x81, 0x1e, 0xb8, 0x94, 0x48, 0xe5, 0x52, 0x55, 0x55, 0xe5, 0xd8, 0xb3, 0x89, 0x55, 0x7f, 0x2c,
0xb6, 0x37, 0x21, 0x54, 0xfc, 0x77, 0xc6, 0xbb, 0xa1, 0xa0, 0x5c, 0xd6, 0x7e, 0x33, 0xe3, 0x37,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -502,23 +502,27 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
i2c_scl = -1;
}
int8_t hw_mosi_pin = !request->arg(F("MOSI")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MOSI")).toInt()));
int8_t hw_miso_pin = !request->arg(F("MISO")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MISO")).toInt()));
int8_t hw_sclk_pin = !request->arg(F("SCLK")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCLK")).toInt()));
#ifdef ESP8266
// cannot change pins on ESP8266
if (hw_mosi_pin >= 0 && hw_mosi_pin != HW_PIN_DATASPI) hw_mosi_pin = HW_PIN_DATASPI;
if (hw_miso_pin >= 0 && hw_miso_pin != HW_PIN_MISOSPI) hw_mosi_pin = HW_PIN_MISOSPI;
if (hw_sclk_pin >= 0 && hw_sclk_pin != HW_PIN_CLOCKSPI) hw_sclk_pin = HW_PIN_CLOCKSPI;
#endif
PinManagerPinType spi[2] = { { hw_mosi_pin, true }, { hw_sclk_pin, true } };
if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && pinManager.allocateMultiplePins(spi, 2, PinOwner::HW_SPI)) {
PinManagerPinType spi[3] = { { hw_mosi_pin, true }, { hw_miso_pin, true }, { hw_sclk_pin, true } };
if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
spi_mosi = hw_mosi_pin;
spi_miso = hw_miso_pin;
spi_sclk = hw_sclk_pin;
// no bus initialisation
} else {
//SPI.end();
DEBUG_PRINTLN(F("Could not allocate SPI pins."));
uint8_t spi[2] = { spi_mosi, spi_sclk };
pinManager.deallocateMultiplePins(spi, 2, PinOwner::HW_SPI); // just in case deallocation of old pins
uint8_t spi[3] = { spi_mosi, spi_miso, spi_sclk };
pinManager.deallocateMultiplePins(spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins
spi_mosi = -1;
spi_miso = -1;
spi_sclk = -1;
}

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2208231
#define VERSION 2208251
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -647,6 +647,7 @@ WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
WLED_GLOBAL int8_t i2c_sda _INIT(-1); // global I2C SDA pin [HW_PIN_SDA] (used for usermods)
WLED_GLOBAL int8_t i2c_scl _INIT(-1); // global I2C SCL pin [HW_PIN_SCL] (used for usermods)
WLED_GLOBAL int8_t spi_mosi _INIT(-1); // global SPI DATA/MOSI pin [HW_PIN_DATASPI] (used for usermods)
WLED_GLOBAL int8_t spi_miso _INIT(-1); // global SPI DATA/MISO pin [HW_PIN_MISOSPI] (used for usermods)
WLED_GLOBAL int8_t spi_sclk _INIT(-1); // global SPI CLOCK/SCLK pin [HW_PIN_CLOCKSPI] (used for usermods)
// global ArduinoJson buffer

View File

@ -636,6 +636,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',SET_F("SDA"),i2c_sda);
sappend('v',SET_F("SCL"),i2c_scl);
sappend('v',SET_F("MOSI"),spi_mosi);
sappend('v',SET_F("MISO"),spi_miso);
sappend('v',SET_F("SCLK"),spi_sclk);
oappend(SET_F("addInfo('SDA','")); oappendi(HW_PIN_SDA); oappend(SET_F("');"));
oappend(SET_F("addInfo('SCL','")); oappendi(HW_PIN_SCL); oappend(SET_F("');"));