kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Merge branch '0_15' into multiwifi
						commit
						d1910e4274
					
				
							
								
								
									
										22
									
								
								CHANGELOG.md
								
								
								
								
							
							
						
						
									
										22
									
								
								CHANGELOG.md
								
								
								
								
							| 
						 | 
				
			
			@ -1,7 +1,27 @@
 | 
			
		|||
## WLED changelog
 | 
			
		||||
 | 
			
		||||
#### Build 2309120 till build 2201060
 | 
			
		||||
#### Build 2309120 till build 2401270
 | 
			
		||||
-   WLED version 0.15.0-a0
 | 
			
		||||
-   BREAKING: Effect: updated Palette effect to support 2D (#3683 by @TripleWhy)
 | 
			
		||||
-   "SuperSync" from WLED MM (by @MoonModules)
 | 
			
		||||
-   Effect: DNA Spiral Effect Speed Fix (#3723 by @Derek4aty1)
 | 
			
		||||
-   Fix for #3693
 | 
			
		||||
-   Orange flash fix (#3196) for transitions
 | 
			
		||||
-   Add own background image upload (#3596 by @WoodyLetsCode)
 | 
			
		||||
-   WLED time overrides (`WLED_NTP_ENABLED`, `WLED_TIMEZONE`, `WLED_UTC_OFFSET`, `WLED_LAT` and `WLED_LON`)
 | 
			
		||||
-   Better sorting and naming of static palettes (by @WoodyLetsCode)
 | 
			
		||||
-   ANIMartRIX usermod and effects (#3673 by @netmindz)
 | 
			
		||||
-   Use canvas instead of CSS gradient for liveview (#3621 by @zanhecht)
 | 
			
		||||
-   Fix for #3672
 | 
			
		||||
-   ColoOrderMap W channel swap (color order overrides now have W swap)
 | 
			
		||||
-   En-/disable LED maps when receiving realtime data (#3554 by @ezcGman)
 | 
			
		||||
-   Added PWM frequency selection to UI (Settings)
 | 
			
		||||
-   Automatically build UI before compiling (#3598, #3666 by @WoodyLetsCode)
 | 
			
		||||
-   Internal: Added *suspend* API to `strip` (`WS2812FX class`)
 | 
			
		||||
-   Possible fix for #3589 & partial fix for #3605
 | 
			
		||||
-   MPU6050 upgrade (#3654 by @willmmiles)
 | 
			
		||||
-   UI internals (#3656 by @WoodyLetsCode)
 | 
			
		||||
-   ColorPicker fix (#3658 by @WoodyLetsCode)
 | 
			
		||||
-   Global JSON buffer guarding (#3648 by @willmmiles, resolves #3641, #3312, #3367, #3637, #3646, #3447)
 | 
			
		||||
-   Effect: Fireworks 1D (fix for matrix trailing strip)
 | 
			
		||||
-   BREAKING: Reduced number of segments (12) on ESP8266 due to less available RAM
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -445,7 +445,7 @@ void BobLightUsermod::pollBob() {
 | 
			
		|||
          //strip.setPixelColor(light_id, RGBW32(red, green, blue, 0));
 | 
			
		||||
          setRealtimePixel(light_id, red, green, blue, 0);
 | 
			
		||||
        } // currently no support for interpolation or speed, we just ignore this
 | 
			
		||||
      } else if (input.startsWith(F("sync"))) {
 | 
			
		||||
      } else if (input.startsWith("sync")) {
 | 
			
		||||
        BobSync();
 | 
			
		||||
      } else {
 | 
			
		||||
        // Client sent gibberish
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,8 +67,8 @@ class WireguardUsermod : public Usermod {
 | 
			
		|||
        JsonObject top = root.createNestedObject(F("WireGuard"));
 | 
			
		||||
        top[F("host")] = endpoint_address;
 | 
			
		||||
        top[F("port")] = endpoint_port;
 | 
			
		||||
        top[F("ip")] = local_ip.toString();
 | 
			
		||||
        top[F("psk")] = preshared_key;
 | 
			
		||||
        top["ip"] = local_ip.toString();
 | 
			
		||||
        top["psk"] = preshared_key;
 | 
			
		||||
        top[F("pem")] = private_key;
 | 
			
		||||
        top[F("pub")] = public_key;
 | 
			
		||||
        top[F("tz")] = posix_tz;
 | 
			
		||||
| 
						 | 
				
			
			@ -77,11 +77,11 @@ class WireguardUsermod : public Usermod {
 | 
			
		|||
    bool readFromConfig(JsonObject& root) {
 | 
			
		||||
        JsonObject top = root[F("WireGuard")];
 | 
			
		||||
 | 
			
		||||
        if (top["host"].isNull() || top["port"].isNull() || top["ip"].isNull() || top["pem"].isNull() || top["pub"].isNull() || top["tz"].isNull()) {
 | 
			
		||||
        if (top[F("host")].isNull() || top[F("port")].isNull() || top["ip"].isNull() || top[F("pem")].isNull() || top[F("pub")].isNull() || top[F("tz")].isNull()) {
 | 
			
		||||
            is_enabled = false;
 | 
			
		||||
            return false;
 | 
			
		||||
        } else {
 | 
			
		||||
            const char* host = top["host"];
 | 
			
		||||
            const char* host = top[F("host")];
 | 
			
		||||
            strncpy(endpoint_address, host, 100);
 | 
			
		||||
 | 
			
		||||
            const char* ip_s = top["ip"];
 | 
			
		||||
| 
						 | 
				
			
			@ -89,16 +89,16 @@ class WireguardUsermod : public Usermod {
 | 
			
		|||
            sscanf(ip_s, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]);
 | 
			
		||||
            local_ip = IPAddress(ip[0], ip[1], ip[2], ip[3]);
 | 
			
		||||
 | 
			
		||||
            const char* pem = top["pem"];
 | 
			
		||||
            const char* pem = top[F("pem")];
 | 
			
		||||
            strncpy(private_key, pem, 45);
 | 
			
		||||
 | 
			
		||||
            const char* pub = top["pub"];
 | 
			
		||||
            const char* pub = top[F("pub")];
 | 
			
		||||
            strncpy(public_key, pub, 45);
 | 
			
		||||
 | 
			
		||||
            const char* tz = top["tz"];
 | 
			
		||||
            const char* tz = top[F("tz")];
 | 
			
		||||
            strncpy(posix_tz, tz, 150);
 | 
			
		||||
 | 
			
		||||
            endpoint_port = top["port"];
 | 
			
		||||
            endpoint_port = top[F("port")];
 | 
			
		||||
 | 
			
		||||
            if (!top["psk"].isNull()) {
 | 
			
		||||
                const char* psk = top["psk"];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -325,8 +325,8 @@ public:
 | 
			
		|||
    void addToConfig(JsonObject& root)
 | 
			
		||||
    {
 | 
			
		||||
      JsonObject modName = root.createNestedObject("id");
 | 
			
		||||
      modName["mdns"] = "wled-word-clock";
 | 
			
		||||
      modName["name"] = "WLED WORD CLOCK";
 | 
			
		||||
      modName[F("mdns")] = "wled-word-clock";
 | 
			
		||||
      modName[F("name")] = "WLED WORD CLOCK";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint16_t getId()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										313
									
								
								wled00/FX.cpp
								
								
								
								
							
							
						
						
									
										313
									
								
								wled00/FX.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -1848,10 +1848,10 @@ uint16_t mode_lightning(void) {
 | 
			
		|||
    }
 | 
			
		||||
    SEGENV.aux1--;
 | 
			
		||||
 | 
			
		||||
    SEGENV.step = millis();
 | 
			
		||||
    SEGENV.step = strip.now;
 | 
			
		||||
    //return random8(4, 10); // each flash only lasts one frame/every 24ms... originally 4-10 milliseconds
 | 
			
		||||
  } else {
 | 
			
		||||
    if (millis() - SEGENV.step > SEGENV.aux0) {
 | 
			
		||||
    if (strip.now - SEGENV.step > SEGENV.aux0) {
 | 
			
		||||
      SEGENV.aux1--;
 | 
			
		||||
      if (SEGENV.aux1 < 2) SEGENV.aux1 = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1859,7 +1859,7 @@ uint16_t mode_lightning(void) {
 | 
			
		|||
      if (SEGENV.aux1 == 2) {
 | 
			
		||||
        SEGENV.aux0 = (random8(255 - SEGMENT.speed) * 100); // delay between strikes
 | 
			
		||||
      }
 | 
			
		||||
      SEGENV.step = millis();
 | 
			
		||||
      SEGENV.step = strip.now;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -1929,22 +1929,102 @@ static const char _data_FX_MODE_JUGGLE[] PROGMEM = "Juggle@!,Trail;;!;;sx=64,ix=
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
uint16_t mode_palette() {
 | 
			
		||||
  uint16_t counter = 0;
 | 
			
		||||
  if (SEGMENT.speed != 0)
 | 
			
		||||
  {
 | 
			
		||||
    counter = (strip.now * ((SEGMENT.speed >> 3) +1)) & 0xFFFF;
 | 
			
		||||
    counter = counter >> 8;
 | 
			
		||||
  }
 | 
			
		||||
  // Set up some compile time constants so that we can handle integer and float based modes using the same code base.
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  using mathType = int32_t;
 | 
			
		||||
  using wideMathType = int64_t;
 | 
			
		||||
  using angleType = uint16_t;
 | 
			
		||||
  constexpr mathType sInt16Scale             = 0x7FFF;
 | 
			
		||||
  constexpr mathType maxAngle                = 0x8000;
 | 
			
		||||
  constexpr mathType staticRotationScale     = 256;
 | 
			
		||||
  constexpr mathType animatedRotationScale   = 1;
 | 
			
		||||
  constexpr int16_t (*sinFunction)(uint16_t) = &sin16;
 | 
			
		||||
  constexpr int16_t (*cosFunction)(uint16_t) = &cos16;
 | 
			
		||||
#else
 | 
			
		||||
  using mathType = float;
 | 
			
		||||
  using wideMathType = float;
 | 
			
		||||
  using angleType = float;
 | 
			
		||||
  constexpr mathType sInt16Scale           = 1.0f;
 | 
			
		||||
  constexpr mathType maxAngle              = M_PI / 256.0;
 | 
			
		||||
  constexpr mathType staticRotationScale   = 1.0f;
 | 
			
		||||
  constexpr mathType animatedRotationScale = M_TWOPI / double(0xFFFF);
 | 
			
		||||
  constexpr float (*sinFunction)(float)    = &sin_t;
 | 
			
		||||
  constexpr float (*cosFunction)(float)    = &cos_t;
 | 
			
		||||
#endif
 | 
			
		||||
  const bool isMatrix = strip.isMatrix;
 | 
			
		||||
  const int cols = SEGMENT.virtualWidth();
 | 
			
		||||
  const int rows = isMatrix ? SEGMENT.virtualHeight() : strip.getActiveSegmentsNum();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SEGLEN; i++)
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
 | 
			
		||||
    SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_MOVING_WRAP, 255));
 | 
			
		||||
  }
 | 
			
		||||
  const int  inputShift           = SEGMENT.speed;
 | 
			
		||||
  const int  inputSize            = SEGMENT.intensity;
 | 
			
		||||
  const int  inputRotation        = SEGMENT.custom1;
 | 
			
		||||
  const bool inputAnimateShift    = SEGMENT.check1;
 | 
			
		||||
  const bool inputAnimateRotation = SEGMENT.check2;
 | 
			
		||||
  const bool inputAssumeSquare    = SEGMENT.check3;
 | 
			
		||||
 | 
			
		||||
  const angleType theta = (!inputAnimateRotation) ? (inputRotation * maxAngle / staticRotationScale) : (((strip.now * ((inputRotation >> 4) +1)) & 0xFFFF) * animatedRotationScale);
 | 
			
		||||
  const mathType sinTheta = sinFunction(theta);
 | 
			
		||||
  const mathType cosTheta = cosFunction(theta);
 | 
			
		||||
 | 
			
		||||
  const mathType maxX    = std::max(1, cols-1);
 | 
			
		||||
  const mathType maxY    = std::max(1, rows-1);
 | 
			
		||||
  // Set up some parameters according to inputAssumeSquare, so that we can handle anamorphic mode using the same code base.
 | 
			
		||||
  const mathType maxXIn  =  inputAssumeSquare ? maxX : mathType(1);
 | 
			
		||||
  const mathType maxYIn  =  inputAssumeSquare ? maxY : mathType(1);
 | 
			
		||||
  const mathType maxXOut = !inputAssumeSquare ? maxX : mathType(1);
 | 
			
		||||
  const mathType maxYOut = !inputAssumeSquare ? maxY : mathType(1);
 | 
			
		||||
  const mathType centerX = sInt16Scale * maxXOut / mathType(2);
 | 
			
		||||
  const mathType centerY = sInt16Scale * maxYOut / mathType(2);
 | 
			
		||||
  // The basic idea for this effect is to rotate a rectangle that is filled with the palette along one axis, then map our
 | 
			
		||||
  // display to it, to find what color a pixel should have.
 | 
			
		||||
  // However, we want a) no areas of solid color (in front of or behind the palette), and b) we want to make use of the full palette.
 | 
			
		||||
  // So the rectangle needs to have exactly the right size. That size depends on the rotation.
 | 
			
		||||
  // This scale computation here only considers one dimension. You can think of it like the rectangle is always scaled so that
 | 
			
		||||
  // the left and right most points always match the left and right side of the display.
 | 
			
		||||
  const mathType scale   = std::abs(sinTheta) + (std::abs(cosTheta) * maxYOut / maxXOut);
 | 
			
		||||
  // 2D simulation:
 | 
			
		||||
  // If we are dealing with a 1D setup, we assume that each segment represents one line on a 2-dimensional display.
 | 
			
		||||
  // The function is called once per segments, so we need to handle one line at a time.
 | 
			
		||||
  const int yFrom = isMatrix ? 0 : strip.getCurrSegmentId();
 | 
			
		||||
  const int yTo   = isMatrix ? maxY : yFrom;
 | 
			
		||||
  for (int y = yFrom; y <= yTo; ++y) {
 | 
			
		||||
    // translate, scale, rotate
 | 
			
		||||
    const mathType ytCosTheta = mathType((wideMathType(cosTheta) * wideMathType(y * sInt16Scale - centerY * maxYIn))/wideMathType(maxYIn * scale));
 | 
			
		||||
    for (int x = 0; x < cols; ++x) {
 | 
			
		||||
      // translate, scale, rotate
 | 
			
		||||
      const mathType xtSinTheta = mathType((wideMathType(sinTheta) * wideMathType(x * sInt16Scale - centerX * maxXIn))/wideMathType(maxXIn * scale));
 | 
			
		||||
      // Map the pixel coordinate to an imaginary-rectangle-coordinate.
 | 
			
		||||
      // The y coordinate doesn't actually matter, as our imaginary rectangle is filled with the palette from left to right,
 | 
			
		||||
      // so all points at a given x-coordinate have the same color.
 | 
			
		||||
      const mathType sourceX = xtSinTheta + ytCosTheta + centerX;
 | 
			
		||||
      // The computation was scaled just right so that the result should always be in range [0, maxXOut], but enforce this anyway
 | 
			
		||||
      // to account for imprecision. Then scale it so that the range is [0, 255], which we can use with the palette.
 | 
			
		||||
      int colorIndex = (std::min(std::max(sourceX, mathType(0)), maxXOut * sInt16Scale) * 255) / (sInt16Scale * maxXOut);
 | 
			
		||||
      // inputSize determines by how much we want to scale the palette:
 | 
			
		||||
      // values < 128 display a fraction of a palette,
 | 
			
		||||
      // values > 128 display multiple palettes.
 | 
			
		||||
      if (inputSize <= 128) {
 | 
			
		||||
        colorIndex = (colorIndex * inputSize) / 128;
 | 
			
		||||
      } else {
 | 
			
		||||
        // Linear function that maps colorIndex 128=>1, 256=>9.
 | 
			
		||||
        // With this function every full palette repetition is exactly 16 configuration steps wide.
 | 
			
		||||
        // That allows displaying exactly 2 repetitions for example.
 | 
			
		||||
        colorIndex = ((inputSize - 112) * colorIndex) / 16;
 | 
			
		||||
      }
 | 
			
		||||
      // Finally, shift the palette a bit.
 | 
			
		||||
      const int paletteOffset = (!inputAnimateShift) ? (inputShift-128) : (((strip.now * ((inputShift >> 3) +1)) & 0xFFFF) >> 8);
 | 
			
		||||
      colorIndex += paletteOffset;
 | 
			
		||||
      const uint32_t color = SEGMENT.color_wheel((uint8_t)colorIndex);
 | 
			
		||||
      if (isMatrix) {
 | 
			
		||||
        SEGMENT.setPixelColorXY(x, y, color);
 | 
			
		||||
      } else {
 | 
			
		||||
        SEGMENT.setPixelColor(x, color);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed;;!;;c3=0,o2=0";
 | 
			
		||||
static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active
 | 
			
		||||
| 
						 | 
				
			
			@ -2899,7 +2979,7 @@ uint16_t mode_bouncing_balls(void) {
 | 
			
		|||
      uint16_t numBalls = (SEGMENT.intensity * (maxNumBalls - 1)) / 255 + 1; // minimum 1 ball
 | 
			
		||||
      const float gravity = -9.81f; // standard value of gravity
 | 
			
		||||
      const bool hasCol2 = SEGCOLOR(2);
 | 
			
		||||
      const unsigned long time = millis();
 | 
			
		||||
      const unsigned long time = strip.now;
 | 
			
		||||
 | 
			
		||||
      if (SEGENV.call == 0) {
 | 
			
		||||
        for (size_t i = 0; i < maxNumBalls; i++) balls[i].lastBounceTime = time;
 | 
			
		||||
| 
						 | 
				
			
			@ -3336,7 +3416,7 @@ uint16_t mode_starburst(void) {
 | 
			
		|||
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
 | 
			
		||||
  uint32_t it = millis();
 | 
			
		||||
  uint32_t it = strip.now;
 | 
			
		||||
 | 
			
		||||
  star* stars = reinterpret_cast<star*>(SEGENV.data);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3692,7 +3772,7 @@ uint16_t mode_tetrix(void) {
 | 
			
		|||
      // initialize dropping on first call or segment full
 | 
			
		||||
      if (SEGENV.call == 0) {
 | 
			
		||||
        drop->stack = 0;                  // reset brick stack size
 | 
			
		||||
        drop->step = millis() + 2000;     // start by fading out strip
 | 
			
		||||
        drop->step = strip.now + 2000;     // start by fading out strip
 | 
			
		||||
        if (SEGMENT.check1) drop->col = 0;// use only one color from palette
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3726,13 +3806,13 @@ uint16_t mode_tetrix(void) {
 | 
			
		|||
        } else {                          // we hit bottom
 | 
			
		||||
          drop->step = 0;                 // proceed with next brick, go back to init
 | 
			
		||||
          drop->stack += drop->brick;     // increase the stack size
 | 
			
		||||
          if (drop->stack >= SEGLEN) drop->step = millis() + 2000; // fade out stack
 | 
			
		||||
          if (drop->stack >= SEGLEN) drop->step = strip.now + 2000; // fade out stack
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (drop->step > 2) {               // fade strip
 | 
			
		||||
        drop->brick = 0;                  // reset brick size (no more growing)
 | 
			
		||||
        if (drop->step > millis()) {
 | 
			
		||||
        if (drop->step > strip.now) {
 | 
			
		||||
          // allow fading of virtual strip
 | 
			
		||||
          for (int i = 0; i < SEGLEN; i++) SEGMENT.blendPixelColor(indexToVStrip(i, stripNr), SEGCOLOR(1), 25); // 10% blend
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -3991,7 +4071,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 strip.now can change from sync
 | 
			
		||||
    SEGENV.aux0 = SEGMENT.speed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4104,9 +4184,9 @@ uint16_t mode_noisepal(void) {                                    // Slow noise
 | 
			
		|||
  CRGBPalette16* palettes = reinterpret_cast<CRGBPalette16*>(SEGENV.data);
 | 
			
		||||
 | 
			
		||||
  uint16_t changePaletteMs = 4000 + SEGMENT.speed *10; //between 4 - 6.5sec
 | 
			
		||||
  if (millis() - SEGENV.step > changePaletteMs)
 | 
			
		||||
  if (strip.now - SEGENV.step > changePaletteMs)
 | 
			
		||||
  {
 | 
			
		||||
    SEGENV.step = millis();
 | 
			
		||||
    SEGENV.step = strip.now;
 | 
			
		||||
 | 
			
		||||
    uint8_t baseI = random8();
 | 
			
		||||
    palettes[1] = CRGBPalette16(CHSV(baseI+random8(64), 255, random8(128,255)), CHSV(baseI+128, 255, random8(128,255)), CHSV(baseI+random8(92), 192, random8(128,255)), CHSV(baseI+random8(92), 255, random8(128,255)));
 | 
			
		||||
| 
						 | 
				
			
			@ -4261,7 +4341,7 @@ uint16_t mode_dancing_shadows(void)
 | 
			
		|||
 | 
			
		||||
  SEGMENT.fill(BLACK);
 | 
			
		||||
 | 
			
		||||
  unsigned long time = millis();
 | 
			
		||||
  unsigned long time = strip.now;
 | 
			
		||||
  bool respawn = false;
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; i < numSpotlights; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4455,8 +4535,8 @@ uint16_t mode_tv_simulator(void) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
    // create a new sceene
 | 
			
		||||
    if (((millis() - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
 | 
			
		||||
      tvSimulator->sceeneStart    = millis();                                               // remember the start of the new sceene
 | 
			
		||||
    if (((strip.now - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
 | 
			
		||||
      tvSimulator->sceeneStart    = strip.now;                                               // remember the start of the new sceene
 | 
			
		||||
      tvSimulator->sceeneDuration = random16(60* 250* colorSpeed, 60* 750 * colorSpeed);    // duration of a "movie sceene" which has similar colors (5 to 15 minutes with max speed slider)
 | 
			
		||||
      tvSimulator->sceeneColorHue = random16(   0, 768);                                    // random start color-tone for the sceene
 | 
			
		||||
      tvSimulator->sceeneColorSat = random8 ( 100, 130 + colorIntensity);                   // random start color-saturation for the sceene
 | 
			
		||||
| 
						 | 
				
			
			@ -4507,11 +4587,11 @@ uint16_t mode_tv_simulator(void) {
 | 
			
		|||
    tvSimulator->fadeTime  = random16(0, tvSimulator->totalTime);   // Pixel-to-pixel transition time
 | 
			
		||||
    if (random8(10) < 3) tvSimulator->fadeTime = 0;                 // Force scene cut 30% of time
 | 
			
		||||
 | 
			
		||||
    tvSimulator->startTime = millis();
 | 
			
		||||
    tvSimulator->startTime = strip.now;
 | 
			
		||||
  } // end of initialization
 | 
			
		||||
 | 
			
		||||
  // how much time is elapsed ?
 | 
			
		||||
  tvSimulator->elapsed = millis() - tvSimulator->startTime;
 | 
			
		||||
  tvSimulator->elapsed = strip.now - tvSimulator->startTime;
 | 
			
		||||
 | 
			
		||||
  // fade from prev volor to next color
 | 
			
		||||
  if (tvSimulator->elapsed < tvSimulator->fadeTime) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4715,7 +4795,7 @@ uint16_t mode_perlinmove(void) {
 | 
			
		|||
  if (SEGLEN == 1) return mode_static();
 | 
			
		||||
  SEGMENT.fade_out(255-SEGMENT.custom1);
 | 
			
		||||
  for (int i = 0; i < SEGMENT.intensity/16 + 1; i++) {
 | 
			
		||||
    uint16_t locn = inoise16(millis()*128/(260-SEGMENT.speed)+i*15000, millis()*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise.
 | 
			
		||||
    uint16_t locn = inoise16(strip.now*128/(260-SEGMENT.speed)+i*15000, strip.now*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise.
 | 
			
		||||
    uint16_t pixloc = map(locn, 50*256, 192*256, 0, SEGLEN-1);                                            // Map that to the length of the strand, and ensure we don't go over.
 | 
			
		||||
    SEGMENT.setPixelColor(pixloc, SEGMENT.color_from_palette(pixloc%255, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -4732,7 +4812,7 @@ static const char _data_FX_MODE_PERLINMOVE[] PROGMEM = "Perlin Move@!,# of pixel
 | 
			
		|||
uint16_t mode_wavesins(void) {
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SEGLEN; i++) {
 | 
			
		||||
    uint8_t bri = sin8(millis()/4 + i * SEGMENT.intensity);
 | 
			
		||||
    uint8_t bri = sin8(strip.now/4 + i * SEGMENT.intensity);
 | 
			
		||||
    uint8_t index = beatsin8(SEGMENT.speed, SEGMENT.custom1, SEGMENT.custom1+SEGMENT.custom2, 0, i * (SEGMENT.custom3<<3)); // custom3 is reduced resolution slider
 | 
			
		||||
    //SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, index, bri, LINEARBLEND));
 | 
			
		||||
    SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0, bri));
 | 
			
		||||
| 
						 | 
				
			
			@ -4750,8 +4830,8 @@ static const char _data_FX_MODE_WAVESINS[] PROGMEM = "Wavesins@!,Brightness vari
 | 
			
		|||
uint16_t mode_FlowStripe(void) {
 | 
			
		||||
 | 
			
		||||
  const uint16_t hl = SEGLEN * 10 / 13;
 | 
			
		||||
  uint8_t hue = millis() / (SEGMENT.speed+1);
 | 
			
		||||
  uint32_t t = millis() / (SEGMENT.intensity/8+1);
 | 
			
		||||
  uint8_t hue = strip.now / (SEGMENT.speed+1);
 | 
			
		||||
  uint32_t t = strip.now / (SEGMENT.intensity/8+1);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SEGLEN; i++) {
 | 
			
		||||
    int c = (abs(i - hl) / hl) * 127;
 | 
			
		||||
| 
						 | 
				
			
			@ -4781,7 +4861,7 @@ uint16_t mode_2DBlackHole(void) {            // By: Stepko https://editor.soulma
 | 
			
		|||
  uint16_t x, y;
 | 
			
		||||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
 | 
			
		||||
  unsigned long t = millis()/128;                 // timebase
 | 
			
		||||
  unsigned long t = strip.now/128;                 // timebase
 | 
			
		||||
  // outer stars
 | 
			
		||||
  for (size_t i = 0; i < 8; i++) {
 | 
			
		||||
    x = beatsin8(SEGMENT.custom1>>3,   0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i);
 | 
			
		||||
| 
						 | 
				
			
			@ -4867,8 +4947,8 @@ uint16_t mode_2Ddna(void) {         // dna originally by by ldirko at https://pa
 | 
			
		|||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(64);
 | 
			
		||||
  for (int i = 0; i < cols; i++) {
 | 
			
		||||
    SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4    ), ColorFromPalette(SEGPALETTE, i*5+millis()/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND));
 | 
			
		||||
    SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+millis()/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND));
 | 
			
		||||
    SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4    ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND));
 | 
			
		||||
    SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND));
 | 
			
		||||
  }
 | 
			
		||||
  SEGMENT.blur(SEGMENT.intensity>>3);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4880,7 +4960,7 @@ static const char _data_FX_MODE_2DDNA[] PROGMEM = "DNA@Scroll speed,Blur;;!;2";
 | 
			
		|||
/////////////////////////
 | 
			
		||||
//     2D DNA Spiral   //
 | 
			
		||||
/////////////////////////
 | 
			
		||||
uint16_t mode_2DDNASpiral() {               // By: ldirko  https://editor.soulmatelights.com/gallery/810 , modified by: Andrew Tuline
 | 
			
		||||
uint16_t mode_2DDNASpiral() {               // By: ldirko  https://editor.soulmatelights.com/gallery/512-dna-spiral-variation , modified by: Andrew Tuline
 | 
			
		||||
  if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
 | 
			
		||||
 | 
			
		||||
  const uint16_t cols = SEGMENT.virtualWidth();
 | 
			
		||||
| 
						 | 
				
			
			@ -4890,10 +4970,10 @@ uint16_t mode_2DDNASpiral() {               // By: ldirko  https://editor.soulma
 | 
			
		|||
    SEGMENT.fill(BLACK);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint8_t speeds = SEGMENT.speed/2 + 1;
 | 
			
		||||
  uint8_t speeds = SEGMENT.speed/2 + 7;
 | 
			
		||||
  uint8_t freq = SEGMENT.intensity/8;
 | 
			
		||||
 | 
			
		||||
  uint32_t ms = millis() / 20;
 | 
			
		||||
  uint32_t ms = strip.now / 20;
 | 
			
		||||
  SEGMENT.fadeToBlackBy(135);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < rows; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4933,7 +5013,7 @@ uint16_t mode_2DDrift() {              // By: Stepko   https://editor.soulmateli
 | 
			
		|||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(128);
 | 
			
		||||
  const uint16_t maxDim = MAX(cols, rows)/2;
 | 
			
		||||
  unsigned long t = millis() / (32 - (SEGMENT.speed>>3));
 | 
			
		||||
  unsigned long t = strip.now / (32 - (SEGMENT.speed>>3));
 | 
			
		||||
  unsigned long t_20 = t/20; // softhack007: pre-calculating this gives about 10% speedup
 | 
			
		||||
  for (float i = 1; i < maxDim; i += 0.25) {
 | 
			
		||||
    float angle = radians(t * (maxDim - i));
 | 
			
		||||
| 
						 | 
				
			
			@ -4972,7 +5052,7 @@ uint16_t mode_2Dfirenoise(void) {               // firenoise2d. By Andrew Tuline
 | 
			
		|||
 | 
			
		||||
  for (int j=0; j < cols; j++) {
 | 
			
		||||
    for (int i=0; i < rows; i++) {
 | 
			
		||||
      indexx = inoise8(j*yscale*rows/255, i*xscale+millis()/4);                                           // We're moving along our Perlin map.
 | 
			
		||||
      indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4);                                           // We're moving along our Perlin map.
 | 
			
		||||
      SEGMENT.setPixelColorXY(j, i, ColorFromPalette(SEGPALETTE, min(i*(indexx)>>4, 255), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
 | 
			
		||||
    } // for i
 | 
			
		||||
  } // for j
 | 
			
		||||
| 
						 | 
				
			
			@ -5203,8 +5283,8 @@ uint16_t mode_2DJulia(void) {                           // An animated Julia set
 | 
			
		|||
  reAl = -0.94299f;               // PixelBlaze example
 | 
			
		||||
  imAg = 0.3162f;
 | 
			
		||||
 | 
			
		||||
  reAl += sin_t((float)millis()/305.f)/20.f;
 | 
			
		||||
  imAg += sin_t((float)millis()/405.f)/20.f;
 | 
			
		||||
  reAl += sin_t((float)strip.now/305.f)/20.f;
 | 
			
		||||
  imAg += sin_t((float)strip.now/405.f)/20.f;
 | 
			
		||||
 | 
			
		||||
  dx = (xmax - xmin) / (cols);     // Scale the delta x and y values to our matrix size.
 | 
			
		||||
  dy = (ymax - ymin) / (rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -5263,7 +5343,7 @@ uint16_t mode_2DLissajous(void) {            // By: Andrew Tuline
 | 
			
		|||
  const uint16_t rows = SEGMENT.virtualHeight();
 | 
			
		||||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(SEGMENT.intensity);
 | 
			
		||||
  uint_fast16_t phase = (millis() * (1 + SEGENV.custom3)) /32;  // allow user to control rotation speed
 | 
			
		||||
  uint_fast16_t phase = (strip.now * (1 + SEGENV.custom3)) /32;  // allow user to control rotation speed
 | 
			
		||||
 | 
			
		||||
  //for (int i=0; i < 4*(cols+rows); i ++) {
 | 
			
		||||
  for (int i=0; i < 256; i ++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5273,7 +5353,7 @@ uint16_t mode_2DLissajous(void) {            // By: Andrew Tuline
 | 
			
		|||
    uint_fast8_t ylocn = cos8(phase/2 + i*2);
 | 
			
		||||
    xlocn = (cols < 2) ? 1 : (map(2*xlocn, 0,511, 0,2*(cols-1)) +1) /2;    // softhack007: "(2* ..... +1) /2" for proper rounding
 | 
			
		||||
    ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2;    // "rows > 1" is needed to avoid div/0 in map()
 | 
			
		||||
    SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(millis()/100+i, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -5423,7 +5503,7 @@ uint16_t mode_2Dnoise(void) {                  // By Andrew Tuline
 | 
			
		|||
 | 
			
		||||
  for (int y = 0; y < rows; y++) {
 | 
			
		||||
    for (int x = 0; x < cols; x++) {
 | 
			
		||||
      uint8_t pixelHue8 = inoise8(x * scale, y * scale, millis() / (16 - SEGMENT.speed/16));
 | 
			
		||||
      uint8_t pixelHue8 = inoise8(x * scale, y * scale, strip.now / (16 - SEGMENT.speed/16));
 | 
			
		||||
      SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, pixelHue8));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -5443,7 +5523,7 @@ uint16_t mode_2DPlasmaball(void) {                   // By: Stepko https://edito
 | 
			
		|||
  const uint16_t rows = SEGMENT.virtualHeight();
 | 
			
		||||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(SEGMENT.custom1>>2);
 | 
			
		||||
  uint_fast32_t t = (millis() * 8) / (256 - SEGMENT.speed);  // optimized to avoid float
 | 
			
		||||
  uint_fast32_t t = (strip.now * 8) / (256 - SEGMENT.speed);  // optimized to avoid float
 | 
			
		||||
  for (int i = 0; i < cols; i++) {
 | 
			
		||||
    uint16_t thisVal = inoise8(i * 30, t, t);
 | 
			
		||||
    uint16_t thisMax = map(thisVal, 0, 255, 0, cols-1);
 | 
			
		||||
| 
						 | 
				
			
			@ -5561,7 +5641,7 @@ uint16_t mode_2DSindots(void) {                             // By: ldirko   http
 | 
			
		|||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3);
 | 
			
		||||
 | 
			
		||||
  byte t1 = millis() / (257 - SEGMENT.speed); // 20;
 | 
			
		||||
  byte t1 = strip.now / (257 - SEGMENT.speed); // 20;
 | 
			
		||||
  byte t2 = sin8(t1) / 4 * 2;
 | 
			
		||||
  for (int i = 0; i < 13; i++) {
 | 
			
		||||
    byte x = sin8(t1 + i * SEGMENT.intensity/8)*(cols-1)/255;  // max index now 255x15/255=15!
 | 
			
		||||
| 
						 | 
				
			
			@ -5600,11 +5680,9 @@ uint16_t mode_2Dsquaredswirl(void) {            // By: Mark Kriegsman. https://g
 | 
			
		|||
  uint8_t n = beatsin8(15, kBorderWidth, rows-kBorderWidth);
 | 
			
		||||
  uint8_t p = beatsin8(20, kBorderWidth, rows-kBorderWidth);
 | 
			
		||||
 | 
			
		||||
  uint16_t ms = millis();
 | 
			
		||||
 | 
			
		||||
  SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, ms/29, 255, LINEARBLEND));
 | 
			
		||||
  SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, ms/41, 255, LINEARBLEND));
 | 
			
		||||
  SEGMENT.addPixelColorXY(k, p, ColorFromPalette(SEGPALETTE, ms/73, 255, LINEARBLEND));
 | 
			
		||||
  SEGMENT.addPixelColorXY(i, m, ColorFromPalette(SEGPALETTE, strip.now/29, 255, LINEARBLEND));
 | 
			
		||||
  SEGMENT.addPixelColorXY(j, n, ColorFromPalette(SEGPALETTE, strip.now/41, 255, LINEARBLEND));
 | 
			
		||||
  SEGMENT.addPixelColorXY(k, p, ColorFromPalette(SEGPALETTE, strip.now/73, 255, LINEARBLEND));
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
} // mode_2Dsquaredswirl()
 | 
			
		||||
| 
						 | 
				
			
			@ -5627,7 +5705,7 @@ uint16_t mode_2DSunradiation(void) {                   // By: ldirko https://edi
 | 
			
		|||
    SEGMENT.fill(BLACK);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unsigned long t = millis() / 4;
 | 
			
		||||
  unsigned long t = strip.now / 4;
 | 
			
		||||
  int index = 0;
 | 
			
		||||
  uint8_t someVal = SEGMENT.speed/4;             // Was 25.
 | 
			
		||||
  for (int j = 0; j < (rows + 2); j++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5759,14 +5837,14 @@ uint16_t mode_2Dcrazybees(void) {
 | 
			
		|||
    int8_t deltaX, deltaY, signX, signY, error;
 | 
			
		||||
    void aimed(uint16_t w, uint16_t h) {
 | 
			
		||||
      //random16_set_seed(millis());
 | 
			
		||||
      aimX = random8(0, w);
 | 
			
		||||
      aimY = random8(0, h);
 | 
			
		||||
      hue = random8();
 | 
			
		||||
      aimX   = random8(0, w);
 | 
			
		||||
      aimY   = random8(0, h);
 | 
			
		||||
      hue    = random8();
 | 
			
		||||
      deltaX = abs(aimX - posX);
 | 
			
		||||
      deltaY = abs(aimY - posY);
 | 
			
		||||
      signX = posX < aimX ? 1 : -1;
 | 
			
		||||
      signY = posY < aimY ? 1 : -1;
 | 
			
		||||
      error = deltaX - deltaY;
 | 
			
		||||
      signX  = posX < aimX ? 1 : -1;
 | 
			
		||||
      signY  = posY < aimY ? 1 : -1;
 | 
			
		||||
      error  = deltaX - deltaY;
 | 
			
		||||
    };
 | 
			
		||||
  } bee_t;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5774,6 +5852,7 @@ uint16_t mode_2Dcrazybees(void) {
 | 
			
		|||
  bee_t *bee = reinterpret_cast<bee_t*>(SEGENV.data);
 | 
			
		||||
 | 
			
		||||
  if (SEGENV.call == 0) {
 | 
			
		||||
    random16_set_seed(strip.now);
 | 
			
		||||
    for (size_t i = 0; i < n; i++) {
 | 
			
		||||
      bee[i].posX = random8(0, cols);
 | 
			
		||||
      bee[i].posY = random8(0, rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -5781,8 +5860,8 @@ uint16_t mode_2Dcrazybees(void) {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (millis() > SEGENV.step) {
 | 
			
		||||
    SEGENV.step = millis() + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1));
 | 
			
		||||
  if (strip.now > SEGENV.step) {
 | 
			
		||||
    SEGENV.step = strip.now + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1));
 | 
			
		||||
 | 
			
		||||
    SEGMENT.fadeToBlackBy(32);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5859,8 +5938,8 @@ uint16_t mode_2Dghostrider(void) {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (millis() > SEGENV.step) {
 | 
			
		||||
    SEGENV.step = millis() + 1024 / (cols+rows);
 | 
			
		||||
  if (strip.now > SEGENV.step) {
 | 
			
		||||
    SEGENV.step = strip.now + 1024 / (cols+rows);
 | 
			
		||||
 | 
			
		||||
    SEGMENT.fadeToBlackBy((SEGMENT.speed>>2)+64);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5948,7 +6027,7 @@ uint16_t mode_2Dfloatingblobs(void) {
 | 
			
		|||
 | 
			
		||||
  // Bounce balls around
 | 
			
		||||
  for (size_t i = 0; i < Amount; i++) {
 | 
			
		||||
    if (SEGENV.step < millis()) blob->color[i] = add8(blob->color[i], 4); // slowly change color
 | 
			
		||||
    if (SEGENV.step < strip.now) blob->color[i] = add8(blob->color[i], 4); // slowly change color
 | 
			
		||||
    // change radius if needed
 | 
			
		||||
    if (blob->grow[i]) {
 | 
			
		||||
      // enlarge radius until it is >= 4
 | 
			
		||||
| 
						 | 
				
			
			@ -5995,7 +6074,7 @@ uint16_t mode_2Dfloatingblobs(void) {
 | 
			
		|||
  }
 | 
			
		||||
  SEGMENT.blur(SEGMENT.custom1>>2);
 | 
			
		||||
 | 
			
		||||
  if (SEGENV.step < millis()) SEGENV.step = millis() + 2000; // change colors every 2 seconds
 | 
			
		||||
  if (SEGENV.step < strip.now) SEGENV.step = strip.now + 2000; // change colors every 2 seconds
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6059,13 +6138,12 @@ uint16_t mode_2Dscrollingtext(void) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  const int  numberOfLetters = strlen(text);
 | 
			
		||||
  const unsigned long now = millis(); // reduce millis() calls
 | 
			
		||||
  int width = (numberOfLetters * rotLW);
 | 
			
		||||
  int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-rotLH)/2;
 | 
			
		||||
  if (width <= cols) {
 | 
			
		||||
    // scroll vertically (e.g. ^^ Way out ^^) if it fits
 | 
			
		||||
    int speed = map(SEGMENT.speed, 0, 255, 5000, 1000);
 | 
			
		||||
    int frac = now % speed + 1;
 | 
			
		||||
    int frac = strip.now % speed + 1;
 | 
			
		||||
    if (SEGMENT.intensity == 255) {
 | 
			
		||||
      yoffset = (2 * frac * rows)/speed - rows;
 | 
			
		||||
    } else if (SEGMENT.intensity == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -6073,7 +6151,7 @@ uint16_t mode_2Dscrollingtext(void) {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (SEGENV.step < now) {
 | 
			
		||||
  if (SEGENV.step < strip.now) {
 | 
			
		||||
    // calculate start offset
 | 
			
		||||
    if (width > cols) {
 | 
			
		||||
      if (SEGMENT.check3) {
 | 
			
		||||
| 
						 | 
				
			
			@ -6082,7 +6160,7 @@ uint16_t mode_2Dscrollingtext(void) {
 | 
			
		|||
      } else                ++SEGENV.aux0 %= width + cols;
 | 
			
		||||
    } else                    SEGENV.aux0  = (cols + width)/2;
 | 
			
		||||
    ++SEGENV.aux1 &= 0xFF; // color shift
 | 
			
		||||
    SEGENV.step = now + map(SEGMENT.speed, 0, 255, 250, 50); // shift letters every ~250ms to ~50ms
 | 
			
		||||
    SEGENV.step = strip.now + map(SEGMENT.speed, 0, 255, 250, 50); // shift letters every ~250ms to ~50ms
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!SEGMENT.check2) SEGMENT.fade_out(255 - (SEGMENT.custom1>>4));  // trail
 | 
			
		||||
| 
						 | 
				
			
			@ -6130,6 +6208,51 @@ uint16_t mode_2Ddriftrose(void) {
 | 
			
		|||
}
 | 
			
		||||
static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;2";
 | 
			
		||||
 | 
			
		||||
/////////////////////////////
 | 
			
		||||
//  2D PLASMA ROTOZOOMER   //
 | 
			
		||||
/////////////////////////////
 | 
			
		||||
// Plasma Rotozoomer by ldirko (c)2020 [https://editor.soulmatelights.com/gallery/457-plasma-rotozoomer], adapted for WLED by Blaz Kristan (AKA blazoncek)
 | 
			
		||||
uint16_t mode_2Dplasmarotozoom() {
 | 
			
		||||
  if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
 | 
			
		||||
 | 
			
		||||
  const uint16_t cols = SEGMENT.virtualWidth();
 | 
			
		||||
  const uint16_t rows = SEGMENT.virtualHeight();
 | 
			
		||||
 | 
			
		||||
  uint16_t dataSize = SEGMENT.length() + sizeof(float);
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
  float *a = reinterpret_cast<float*>(SEGENV.data);
 | 
			
		||||
  byte *plasma = reinterpret_cast<byte*>(SEGENV.data+sizeof(float));
 | 
			
		||||
 | 
			
		||||
  uint16_t ms = strip.now/15;  
 | 
			
		||||
 | 
			
		||||
  // plasma
 | 
			
		||||
  for (int j = 0; j < rows; j++) {
 | 
			
		||||
    int index = j*cols;
 | 
			
		||||
    for (int i = 0; i < cols; i++) {
 | 
			
		||||
      if (SEGMENT.check1) plasma[index+i] = (i * 4 ^ j * 4) + ms / 6;
 | 
			
		||||
      else                plasma[index+i] = inoise8(i * 40, j * 40, ms);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // rotozoom
 | 
			
		||||
  float f       = (sin_t(*a/2)+((128-SEGMENT.intensity)/128.0f)+1.1f)/1.5f;  // scale factor
 | 
			
		||||
  float kosinus = cos_t(*a) * f;
 | 
			
		||||
  float sinus   = sin_t(*a) * f;
 | 
			
		||||
  for (int i = 0; i < cols; i++) {
 | 
			
		||||
    float u1 = i * kosinus;
 | 
			
		||||
    float v1 = i * sinus;
 | 
			
		||||
    for (int j = 0; j < rows; j++) {
 | 
			
		||||
        byte u = abs8(u1 - j * sinus) % cols;
 | 
			
		||||
        byte v = abs8(v1 + j * kosinus) % rows;
 | 
			
		||||
        SEGMENT.setPixelColorXY(i, j, SEGMENT.color_from_palette(plasma[v*cols+u], false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  *a -= 0.03f + float(SEGENV.speed-128)*0.0002f;  // rotation speed
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
static const char _data_FX_MODE_2DPLASMAROTOZOOM[] PROGMEM = "Rotozoomer@!,Scale,,,,Alt;;!;2;pal=54";
 | 
			
		||||
 | 
			
		||||
#endif // WLED_DISABLE_2D
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6280,7 +6403,6 @@ uint16_t mode_2DSwirl(void) {
 | 
			
		|||
  uint8_t  j = beatsin8( 41*SEGMENT.speed/255, borderWidth, rows - borderWidth);
 | 
			
		||||
  uint8_t ni = (cols - 1) - i;
 | 
			
		||||
  uint8_t nj = (cols - 1) - j;
 | 
			
		||||
  uint16_t ms = millis();
 | 
			
		||||
 | 
			
		||||
  um_data_t *um_data;
 | 
			
		||||
  if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -6290,12 +6412,12 @@ uint16_t mode_2DSwirl(void) {
 | 
			
		|||
  float   volumeSmth  = *(float*)   um_data->u_data[0]; //ewowi: use instead of sampleAvg???
 | 
			
		||||
  int16_t volumeRaw   = *(int16_t*) um_data->u_data[1];
 | 
			
		||||
 | 
			
		||||
  SEGMENT.addPixelColorXY( i, j, ColorFromPalette(SEGPALETTE, (ms / 11 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 11, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY( j, i, ColorFromPalette(SEGPALETTE, (ms / 13 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 13, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(ni,nj, ColorFromPalette(SEGPALETTE, (ms / 17 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 17, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(nj,ni, ColorFromPalette(SEGPALETTE, (ms / 29 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 29, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY( i,nj, ColorFromPalette(SEGPALETTE, (ms / 37 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 37, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(ni, j, ColorFromPalette(SEGPALETTE, (ms / 41 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 41, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY( i, j, ColorFromPalette(SEGPALETTE, (strip.now / 11 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 11, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY( j, i, ColorFromPalette(SEGPALETTE, (strip.now / 13 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 13, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(ni,nj, ColorFromPalette(SEGPALETTE, (strip.now / 17 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 17, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(nj,ni, ColorFromPalette(SEGPALETTE, (strip.now / 29 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 29, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY( i,nj, ColorFromPalette(SEGPALETTE, (strip.now / 37 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 37, 200, 255);
 | 
			
		||||
  SEGMENT.addPixelColorXY(ni, j, ColorFromPalette(SEGPALETTE, (strip.now / 41 + volumeSmth*4), volumeRaw * SEGMENT.intensity / 64, LINEARBLEND)); //CHSV( ms / 41, 200, 255);
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
} // mode_2DSwirl()
 | 
			
		||||
| 
						 | 
				
			
			@ -6321,7 +6443,7 @@ uint16_t mode_2DWaverly(void) {
 | 
			
		|||
 | 
			
		||||
  SEGMENT.fadeToBlackBy(SEGMENT.speed);
 | 
			
		||||
 | 
			
		||||
  long t = millis() / 2;
 | 
			
		||||
  long t = strip.now / 2;
 | 
			
		||||
  for (int i = 0; i < cols; i++) {
 | 
			
		||||
    uint16_t thisVal = (1 + SEGMENT.intensity/64) * inoise8(i * 45 , t , t)/2;
 | 
			
		||||
    // use audio if available
 | 
			
		||||
| 
						 | 
				
			
			@ -6383,7 +6505,7 @@ uint16_t mode_gravcenter(void) {                // Gravcenter. By Andrew Tuline.
 | 
			
		|||
  uint8_t gravity = 8 - SEGMENT.speed/32;
 | 
			
		||||
 | 
			
		||||
  for (int i=0; i<tempsamp; i++) {
 | 
			
		||||
    uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
 | 
			
		||||
    uint8_t index = inoise8(i*segmentSampleAvg+strip.now, 5000+i*segmentSampleAvg);
 | 
			
		||||
    SEGMENT.setPixelColor(i+SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2-i-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -6394,8 +6516,8 @@ uint16_t mode_gravcenter(void) {                // Gravcenter. By Andrew Tuline.
 | 
			
		|||
    gravcen->topLED--;
 | 
			
		||||
 | 
			
		||||
  if (gravcen->topLED >= 0) {
 | 
			
		||||
    SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
  gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6435,7 +6557,7 @@ uint16_t mode_gravcentric(void) {                     // Gravcentric. By Andrew
 | 
			
		|||
  uint8_t gravity = 8 - SEGMENT.speed/32;
 | 
			
		||||
 | 
			
		||||
  for (int i=0; i<tempsamp; i++) {
 | 
			
		||||
    uint8_t index = segmentSampleAvg*24+millis()/200;
 | 
			
		||||
    uint8_t index = segmentSampleAvg*24+strip.now/200;
 | 
			
		||||
    SEGMENT.setPixelColor(i+SEGLEN/2, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2-1-i, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -6484,7 +6606,7 @@ uint16_t mode_gravimeter(void) {                // Gravmeter. By Andrew Tuline.
 | 
			
		|||
  uint8_t gravity = 8 - SEGMENT.speed/32;
 | 
			
		||||
 | 
			
		||||
  for (int i=0; i<tempsamp; i++) {
 | 
			
		||||
    uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
 | 
			
		||||
    uint8_t index = inoise8(i*segmentSampleAvg+strip.now, 5000+i*segmentSampleAvg);
 | 
			
		||||
    SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6494,7 +6616,7 @@ uint16_t mode_gravimeter(void) {                // Gravmeter. By Andrew Tuline.
 | 
			
		|||
    gravcen->topLED--;
 | 
			
		||||
 | 
			
		||||
  if (gravcen->topLED > 0) {
 | 
			
		||||
    SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
  gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6519,7 +6641,7 @@ uint16_t mode_juggles(void) {                   // Juggles. By Andrew Tuline.
 | 
			
		|||
  uint16_t my_sampleAgc = fmax(fmin(volumeSmth, 255.0), 0);
 | 
			
		||||
 | 
			
		||||
  for (size_t i=0; i<SEGMENT.intensity/32+1U; i++) {
 | 
			
		||||
    SEGMENT.setPixelColor(beatsin16(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis()/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc));
 | 
			
		||||
    SEGMENT.setPixelColor(beatsin16(SEGMENT.speed/4+i*2,0,SEGLEN-1), color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now/4+i*2, false, PALETTE_SOLID_WRAP, 0), my_sampleAgc));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -6551,7 +6673,7 @@ uint16_t mode_matripix(void) {                  // Matripix. By Andrew Tuline.
 | 
			
		|||
 | 
			
		||||
    int pixBri = volumeRaw * SEGMENT.intensity / 64;
 | 
			
		||||
    for (int i = 0; i < SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0), pixBri));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0), pixBri));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -6615,7 +6737,7 @@ uint16_t mode_noisefire(void) {                 // Noisefire. By Andrew Tuline.
 | 
			
		|||
  if (SEGENV.call == 0) SEGMENT.fill(BLACK);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SEGLEN; i++) {
 | 
			
		||||
    uint16_t index = inoise8(i*SEGMENT.speed/64,millis()*SEGMENT.speed/64*SEGLEN/255);  // X location is constant, but we move along the Y at the rate of millis(). By Andrew Tuline.
 | 
			
		||||
    uint16_t index = inoise8(i*SEGMENT.speed/64,strip.now*SEGMENT.speed/64*SEGLEN/255);  // X location is constant, but we move along the Y at the rate of millis(). By Andrew Tuline.
 | 
			
		||||
    index = (255 - i*256/SEGLEN) * index/(256-SEGMENT.intensity);                       // Now we need to scale index so that it gets blacker as we get close to one of the ends.
 | 
			
		||||
                                                                                        // This is a simple y=mx+b equation that's been scaled. index/128 is another scaling.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6687,7 +6809,7 @@ uint16_t mode_pixelwave(void) {                 // Pixelwave. By Andrew Tuline.
 | 
			
		|||
 | 
			
		||||
    int pixBri = volumeRaw * SEGMENT.intensity / 64;
 | 
			
		||||
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0), pixBri));
 | 
			
		||||
    SEGMENT.setPixelColor(SEGLEN/2, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0), pixBri));
 | 
			
		||||
    for (int i = SEGLEN - 1; i > SEGLEN/2; i--)   SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
 | 
			
		||||
    for (int i = 0; i < SEGLEN/2; i++)            SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // move to the right
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -6775,7 +6897,7 @@ uint16_t mode_puddlepeak(void) {                // Puddlepeak. By Andrew Tuline.
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  for (int i=0; i<size; i++) {                            // Flash the LED's.
 | 
			
		||||
    SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -6807,7 +6929,7 @@ uint16_t mode_puddles(void) {                   // Puddles. By Andrew Tuline.
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  for (int i=0; i<size; i++) {                          // Flash the LED's.
 | 
			
		||||
    SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
    SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -6830,7 +6952,7 @@ uint16_t mode_pixels(void) {                    // Pixels. By Andrew Tuline.
 | 
			
		|||
  }
 | 
			
		||||
  float   volumeSmth   = *(float*)  um_data->u_data[0];
 | 
			
		||||
 | 
			
		||||
  myVals[millis()%32] = volumeSmth;    // filling values semi randomly
 | 
			
		||||
  myVals[strip.now%32] = volumeSmth;    // filling values semi randomly
 | 
			
		||||
 | 
			
		||||
  SEGMENT.fade_out(64+(SEGMENT.speed>>1));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7188,7 +7310,7 @@ uint16_t mode_noisemove(void) {                 // Noisemove.    By: Andrew Tuli
 | 
			
		|||
 | 
			
		||||
  uint8_t numBins = map(SEGMENT.intensity,0,255,0,16);    // Map slider to fftResult bins.
 | 
			
		||||
  for (int i=0; i<numBins; i++) {                         // How many active bins are we using.
 | 
			
		||||
    uint16_t locn = inoise16(millis()*SEGMENT.speed+i*50000, millis()*SEGMENT.speed);   // Get a new pixel location from moving noise.
 | 
			
		||||
    uint16_t locn = inoise16(strip.now*SEGMENT.speed+i*50000, strip.now*SEGMENT.speed);   // Get a new pixel location from moving noise.
 | 
			
		||||
    locn = map(locn, 7500, 58000, 0, SEGLEN-1);           // Map that to the length of the strand, and ensure we don't go over.
 | 
			
		||||
    SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i*64, false, PALETTE_SOLID_WRAP, 0), fftResult[i % 16]*4));
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -7313,8 +7435,8 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
 | 
			
		|||
  if (SEGENV.call == 0) for (int i=0; i<cols; i++) previousBarHeight[i] = 0;
 | 
			
		||||
 | 
			
		||||
  bool rippleTime = false;
 | 
			
		||||
  if (millis() - SEGENV.step >= (256U - SEGMENT.intensity)) {
 | 
			
		||||
    SEGENV.step = millis();
 | 
			
		||||
  if (strip.now - SEGENV.step >= (256U - SEGMENT.intensity)) {
 | 
			
		||||
    SEGENV.step = strip.now;
 | 
			
		||||
    rippleTime = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7522,7 +7644,7 @@ uint16_t mode_2Ddistortionwaves() {
 | 
			
		|||
 | 
			
		||||
  uint8_t  w = 2;
 | 
			
		||||
 | 
			
		||||
  uint16_t a  = millis()/32;
 | 
			
		||||
  uint16_t a  = strip.now/32;
 | 
			
		||||
  uint16_t a2 = a/2;
 | 
			
		||||
  uint16_t a3 = a/3;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7740,7 +7862,7 @@ uint16_t mode_2Dwavingcell() {
 | 
			
		|||
  const uint16_t cols = SEGMENT.virtualWidth();
 | 
			
		||||
  const uint16_t rows = SEGMENT.virtualHeight();
 | 
			
		||||
 | 
			
		||||
  uint32_t t = millis()/(257-SEGMENT.speed);
 | 
			
		||||
  uint32_t t = strip.now/(257-SEGMENT.speed);
 | 
			
		||||
  uint8_t aX = SEGMENT.custom1/16 + 9;
 | 
			
		||||
  uint8_t aY = SEGMENT.custom2/16 + 1;
 | 
			
		||||
  uint8_t aZ = SEGMENT.custom3 + 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -7945,6 +8067,7 @@ void WS2812FX::setupEffectData() {
 | 
			
		|||
 | 
			
		||||
  // --- 2D  effects ---
 | 
			
		||||
#ifndef WLED_DISABLE_2D
 | 
			
		||||
  addEffect(FX_MODE_2DPLASMAROTOZOOM, &mode_2Dplasmarotozoom, _data_FX_MODE_2DPLASMAROTOZOOM);
 | 
			
		||||
  addEffect(FX_MODE_2DSPACESHIPS, &mode_2Dspaceships, _data_FX_MODE_2DSPACESHIPS);
 | 
			
		||||
  addEffect(FX_MODE_2DCRAZYBEES, &mode_2Dcrazybees, _data_FX_MODE_2DCRAZYBEES);
 | 
			
		||||
  addEffect(FX_MODE_2DGHOSTRIDER, &mode_2Dghostrider, _data_FX_MODE_2DGHOSTRIDER);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -241,7 +241,7 @@
 | 
			
		|||
#define FX_MODE_CHUNCHUN               111
 | 
			
		||||
#define FX_MODE_DANCING_SHADOWS        112
 | 
			
		||||
#define FX_MODE_WASHING_MACHINE        113
 | 
			
		||||
// #define FX_MODE_CANDY_CANE             114  // removed in 0.14!
 | 
			
		||||
#define FX_MODE_2DPLASMAROTOZOOM       114 // was Candy Cane prior to 0.14 (use Chase 2)
 | 
			
		||||
#define FX_MODE_BLENDS                 115
 | 
			
		||||
#define FX_MODE_TV_SIMULATOR           116
 | 
			
		||||
#define FX_MODE_DYNAMIC_SMOOTH         117 // candidate for removal (check3 in dynamic)
 | 
			
		||||
| 
						 | 
				
			
			@ -802,8 +802,7 @@ class WS2812FX {  // 96 bytes
 | 
			
		|||
      getActiveSegmentsNum(void),
 | 
			
		||||
      getFirstSelectedSegId(void),
 | 
			
		||||
      getLastActiveSegmentId(void),
 | 
			
		||||
      getActiveSegsLightCapabilities(bool selectedOnly = false),
 | 
			
		||||
      setPixelSegment(uint8_t n);
 | 
			
		||||
      getActiveSegsLightCapabilities(bool selectedOnly = false);
 | 
			
		||||
 | 
			
		||||
    inline uint8_t getBrightness(void)    { return _brightness; }       // returns current strip brightness
 | 
			
		||||
    inline uint8_t getMaxSegments(void)   { return MAX_NUM_SEGMENTS; }  // returns maximum number of supported segments (fixed value)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -440,6 +440,7 @@ uint8_t IRAM_ATTR Segment::currentMode() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
 | 
			
		||||
  if (slot >= NUM_COLORS) slot = 0;
 | 
			
		||||
#ifndef WLED_DISABLE_MODE_BLEND
 | 
			
		||||
  return isInTransition() ? color_blend(_t->_segT._colorT[slot], colors[slot], progress(), true) : colors[slot];
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,7 +1026,7 @@ void Segment::blur(uint8_t blur_amount) {
 | 
			
		|||
 * Inspired by the Adafruit examples.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t Segment::color_wheel(uint8_t pos) {
 | 
			
		||||
  if (palette) return color_from_palette(pos, false, true, 0);
 | 
			
		||||
  if (palette) return color_from_palette(pos, false, true, 0); // perhaps "strip.paletteBlend < 2" should be better instead of "true"
 | 
			
		||||
  uint8_t w = W(currentColor(0));
 | 
			
		||||
  pos = 255 - pos;
 | 
			
		||||
  if (pos < 85) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1056,6 +1057,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
 | 
			
		|||
 | 
			
		||||
  uint8_t paletteIndex = i;
 | 
			
		||||
  if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
 | 
			
		||||
  // paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
 | 
			
		||||
  if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
 | 
			
		||||
  CRGBPalette16 curPal;
 | 
			
		||||
  curPal = currentPalette(curPal, palette);
 | 
			
		||||
| 
						 | 
				
			
			@ -1140,7 +1142,7 @@ void WS2812FX::service() {
 | 
			
		|||
 | 
			
		||||
  _isServicing = true;
 | 
			
		||||
  _segment_index = 0;
 | 
			
		||||
  Segment::handleRandomPalette(); // move it into for loop when each segment has individual random palette
 | 
			
		||||
 | 
			
		||||
  for (segment &seg : _segments) {
 | 
			
		||||
    if (_suspend) return; // immediately stop processing segments if suspend requested during service()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1203,6 +1205,7 @@ void WS2812FX::service() {
 | 
			
		|||
  #endif
 | 
			
		||||
  if (doShow) {
 | 
			
		||||
    yield();
 | 
			
		||||
    Segment::handleRandomPalette(); // slowly transtion random palette; move it into for loop when each segment has individual random palette
 | 
			
		||||
    show();
 | 
			
		||||
  }
 | 
			
		||||
  #ifdef WLED_DEBUG
 | 
			
		||||
| 
						 | 
				
			
			@ -1453,6 +1456,7 @@ void WS2812FX::resetSegments() {
 | 
			
		|||
  segment seg = Segment(0, _length);
 | 
			
		||||
  #endif
 | 
			
		||||
  _segments.push_back(seg);
 | 
			
		||||
  _segments.shrink_to_fit(); // just in case ...
 | 
			
		||||
  _mainSegment = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1571,18 +1575,7 @@ bool WS2812FX::checkSegmentAlignment() {
 | 
			
		|||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
 | 
			
		||||
//Note: If called in an interrupt (e.g. JSON API), original segment must be restored,
 | 
			
		||||
//otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread
 | 
			
		||||
uint8_t WS2812FX::setPixelSegment(uint8_t n) {
 | 
			
		||||
  uint8_t prevSegId = _segment_index;
 | 
			
		||||
  if (n < _segments.size()) {
 | 
			
		||||
    _segment_index = n;
 | 
			
		||||
    _virtualSegmentLength = _segments[_segment_index].virtualLength();
 | 
			
		||||
  }
 | 
			
		||||
  return prevSegId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// used by analog clock overlay
 | 
			
		||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
 | 
			
		||||
  if (i2 < i) std::swap(i,i2);
 | 
			
		||||
  for (unsigned x = i; x <= i2; x++) setPixelColor(x, col);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,11 @@
 | 
			
		|||
#define I_8266_U1_UCS_4 54
 | 
			
		||||
#define I_8266_DM_UCS_4 55
 | 
			
		||||
#define I_8266_BB_UCS_4 56
 | 
			
		||||
//ESP8266 APA106
 | 
			
		||||
#define I_8266_U0_APA106_3 81
 | 
			
		||||
#define I_8266_U1_APA106_3 82
 | 
			
		||||
#define I_8266_DM_APA106_3 83
 | 
			
		||||
#define I_8266_BB_APA106_3 84
 | 
			
		||||
 | 
			
		||||
/*** ESP32 Neopixel methods ***/
 | 
			
		||||
//RGB
 | 
			
		||||
| 
						 | 
				
			
			@ -100,6 +105,10 @@
 | 
			
		|||
#define I_32_I0_UCS_4 61
 | 
			
		||||
#define I_32_I1_UCS_4 62
 | 
			
		||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
 | 
			
		||||
#define I_32_RN_APA106_3 85
 | 
			
		||||
#define I_32_I0_APA106_3 86
 | 
			
		||||
#define I_32_I1_APA106_3 87
 | 
			
		||||
#define I_32_BB_APA106_3 88  // bitbangging on ESP32 not recommended
 | 
			
		||||
 | 
			
		||||
//APA102
 | 
			
		||||
#define I_HS_DOT_3 39 //hardware SPI
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +171,11 @@
 | 
			
		|||
#define B_8266_U1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Uart1Ws2813Method, NeoGammaNullMethod>   //4 chan, esp8266, gpio2
 | 
			
		||||
#define B_8266_DM_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Dma800KbpsMethod, NeoGammaNullMethod>    //4 chan, esp8266, gpio3
 | 
			
		||||
#define B_8266_BB_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266BitBang800KbpsMethod, NeoGammaNullMethod> //4 chan, esp8266, bb (any pin)
 | 
			
		||||
//APA106
 | 
			
		||||
#define B_8266_U0_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart0Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio1
 | 
			
		||||
#define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2
 | 
			
		||||
#define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod>  //3 chan, esp8266, gpio3
 | 
			
		||||
#define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*** ESP32 Neopixel methods ***/
 | 
			
		||||
| 
						 | 
				
			
			@ -229,6 +243,14 @@
 | 
			
		|||
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
 | 
			
		||||
#endif
 | 
			
		||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
 | 
			
		||||
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
 | 
			
		||||
#ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
 | 
			
		||||
#endif
 | 
			
		||||
//#define B_32_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -327,6 +349,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -379,6 +405,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Begin(); break;
 | 
			
		||||
      case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Begin(); break;
 | 
			
		||||
      // ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
 | 
			
		||||
      case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
 | 
			
		||||
      case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +461,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: busPtr = new B_8266_U1_UCS_4(len, pins[0]); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: busPtr = new B_8266_DM_UCS_4(len, pins[0]); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: busPtr = new B_8266_BB_UCS_4(len, pins[0]); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: busPtr = new B_8266_U0_APA106_3(len, pins[0]); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -479,6 +517,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: busPtr = new B_32_BB_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
 | 
			
		||||
      case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: busPtr = new B_32_BB_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      // for 2-wire: pins[1] is clk, pins[0] is dat.  begin expects (len, clk, dat)
 | 
			
		||||
      case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -528,6 +574,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -580,6 +630,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
      case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -625,6 +683,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U0_UCS_4: return (static_cast<B_8266_U0_UCS_4*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_U1_UCS_4: return (static_cast<B_8266_U1_UCS_4*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: return (static_cast<B_8266_DM_UCS_4*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: return (static_cast<B_8266_U0_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +739,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: return (static_cast<B_32_BB_UCS_4*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: return (static_cast<B_32_BB_APA106_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
      case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -747,6 +817,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -799,6 +873,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
 | 
			
		||||
      case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
      case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -845,6 +927,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -897,6 +983,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
      case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -944,6 +1038,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: { Rgbw64Color c = (static_cast<B_8266_U1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
 | 
			
		||||
      case I_8266_DM_UCS_4: { Rgbw64Color c = (static_cast<B_8266_DM_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
 | 
			
		||||
      case I_8266_BB_UCS_4: { Rgbw64Color c = (static_cast<B_8266_BB_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
 | 
			
		||||
      case I_8266_U0_APA106_3: col = (static_cast<B_8266_U0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -996,6 +1094,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: col = (static_cast<B_32_BB_UCS_4*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: col = (static_cast<B_32_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
      case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1061,6 +1167,10 @@ class PolyBus {
 | 
			
		|||
      case I_8266_U1_UCS_4: delete (static_cast<B_8266_U1_UCS_4*>(busPtr)); break;
 | 
			
		||||
      case I_8266_DM_UCS_4: delete (static_cast<B_8266_DM_UCS_4*>(busPtr)); break;
 | 
			
		||||
      case I_8266_BB_UCS_4: delete (static_cast<B_8266_BB_UCS_4*>(busPtr)); break;
 | 
			
		||||
      case I_8266_U0_APA106_3: delete (static_cast<B_8266_U0_APA106_3*>(busPtr)); break;
 | 
			
		||||
      case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break;
 | 
			
		||||
      case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break;
 | 
			
		||||
      case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
      case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,6 +1223,14 @@ class PolyBus {
 | 
			
		|||
      case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_UCS_4: delete (static_cast<B_32_BB_UCS_4*>(busPtr)); break;
 | 
			
		||||
      case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break;
 | 
			
		||||
      #ifndef WLED_NO_I2S0_PIXELBUS
 | 
			
		||||
      case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #ifndef WLED_NO_I2S1_PIXELBUS
 | 
			
		||||
      case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
 | 
			
		||||
      #endif
 | 
			
		||||
//      case I_32_BB_APA106_3: delete (static_cast<B_32_BB_APA106_3*>(busPtr)); break;
 | 
			
		||||
    #endif
 | 
			
		||||
      case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
 | 
			
		||||
      case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1172,6 +1290,8 @@ class PolyBus {
 | 
			
		|||
          return I_8266_U0_UCS_3 + offset;
 | 
			
		||||
        case TYPE_UCS8904:
 | 
			
		||||
          return I_8266_U0_UCS_4 + offset;
 | 
			
		||||
        case TYPE_APA106:
 | 
			
		||||
          return I_8266_U0_APA106_3 + offset;
 | 
			
		||||
      }
 | 
			
		||||
      #else //ESP32
 | 
			
		||||
      uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1
 | 
			
		||||
| 
						 | 
				
			
			@ -1210,6 +1330,8 @@ class PolyBus {
 | 
			
		|||
          return I_32_RN_UCS_3 + offset;
 | 
			
		||||
        case TYPE_UCS8904:
 | 
			
		||||
          return I_32_RN_UCS_4 + offset;
 | 
			
		||||
        case TYPE_APA106:
 | 
			
		||||
          return I_32_RN_APA106_3 + offset;
 | 
			
		||||
      }
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -161,6 +161,10 @@
 | 
			
		|||
#define AP_BEHAVIOR_NO_CONN               1     //Open when no connection (either after boot or if connection is lost)
 | 
			
		||||
#define AP_BEHAVIOR_ALWAYS                2     //Always open
 | 
			
		||||
#define AP_BEHAVIOR_BUTTON_ONLY           3     //Only when button pressed for 6 sec
 | 
			
		||||
#define AP_BEHAVIOR_TEMPORARY             4     //Open AP when no connection after boot but only temporary
 | 
			
		||||
#ifndef WLED_AP_TIMEOUT
 | 
			
		||||
  #define WLED_AP_TIMEOUT            300000     //Temporary AP timeout
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//Notifier callMode
 | 
			
		||||
#define CALL_MODE_INIT           0     //no updates on init, can be used to disable updates
 | 
			
		||||
| 
						 | 
				
			
			@ -239,6 +243,7 @@
 | 
			
		|||
#define TYPE_WS2811_400KHZ       24            //half-speed WS2812 protocol, used by very old WS2811 units
 | 
			
		||||
#define TYPE_TM1829              25
 | 
			
		||||
#define TYPE_UCS8903             26
 | 
			
		||||
#define TYPE_APA106              27
 | 
			
		||||
#define TYPE_UCS8904             29            //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
 | 
			
		||||
#define TYPE_SK6812_RGBW         30
 | 
			
		||||
#define TYPE_TM1814              31
 | 
			
		||||
| 
						 | 
				
			
			@ -296,19 +301,20 @@
 | 
			
		|||
#define BTN_TYPE_TOUCH_SWITCH     9
 | 
			
		||||
 | 
			
		||||
//Ethernet board types
 | 
			
		||||
#define WLED_NUM_ETH_TYPES       11
 | 
			
		||||
#define WLED_NUM_ETH_TYPES        12
 | 
			
		||||
 | 
			
		||||
#define WLED_ETH_NONE             0
 | 
			
		||||
#define WLED_ETH_WT32_ETH01       1
 | 
			
		||||
#define WLED_ETH_ESP32_POE        2
 | 
			
		||||
#define WLED_ETH_WESP32           3
 | 
			
		||||
#define WLED_ETH_QUINLED          4
 | 
			
		||||
#define WLED_ETH_TWILIGHTLORD     5
 | 
			
		||||
#define WLED_ETH_ESP32DEUX        6
 | 
			
		||||
#define WLED_ETH_ESP32ETHKITVE    7
 | 
			
		||||
#define WLED_ETH_QUINLED_OCTA     8
 | 
			
		||||
#define WLED_ETH_ABCWLEDV43ETH    9
 | 
			
		||||
#define WLED_ETH_SERG74          10
 | 
			
		||||
#define WLED_ETH_NONE              0
 | 
			
		||||
#define WLED_ETH_WT32_ETH01        1
 | 
			
		||||
#define WLED_ETH_ESP32_POE         2
 | 
			
		||||
#define WLED_ETH_WESP32            3
 | 
			
		||||
#define WLED_ETH_QUINLED           4
 | 
			
		||||
#define WLED_ETH_TWILIGHTLORD      5
 | 
			
		||||
#define WLED_ETH_ESP32DEUX         6
 | 
			
		||||
#define WLED_ETH_ESP32ETHKITVE     7
 | 
			
		||||
#define WLED_ETH_QUINLED_OCTA      8
 | 
			
		||||
#define WLED_ETH_ABCWLEDV43ETH     9
 | 
			
		||||
#define WLED_ETH_SERG74           10
 | 
			
		||||
#define WLED_ETH_ESP32_POE_WROVER 11
 | 
			
		||||
 | 
			
		||||
//Hue error codes
 | 
			
		||||
#define HUE_ERROR_INACTIVE        0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2161,7 +2161,7 @@ function selGrp(g)
 | 
			
		|||
	var sel = gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`);
 | 
			
		||||
	var obj = {"seg":[]};
 | 
			
		||||
	for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":false});
 | 
			
		||||
	if (sel) for (let s of sel||[]) {
 | 
			
		||||
	for (let s of (sel||[])) {
 | 
			
		||||
		let i = parseInt(s.id.substring(3));
 | 
			
		||||
		obj.seg[i] = {"id":i,"sel":true};
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -394,6 +394,7 @@ ${i+1}:
 | 
			
		|||
<option value="24">400kHz</option>\
 | 
			
		||||
<option value="25">TM1829</option>\
 | 
			
		||||
<option value="26">UCS8903</option>\
 | 
			
		||||
<option value="27">APA106/PL9823</option>\
 | 
			
		||||
<option value="29">UCS8904 RGBW</option>\
 | 
			
		||||
<option value="50">WS2801</option>\
 | 
			
		||||
<option value="51">APA102</option>\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,10 +212,12 @@ Static subnet mask:<br>
 | 
			
		|||
		Access Point WiFi channel: <input name="AC" type="number" class="xs" min="1" max="13" required><br>
 | 
			
		||||
		AP opens:
 | 
			
		||||
		<select name="AB">
 | 
			
		||||
		<option value="0">No connection after boot</option>
 | 
			
		||||
		<option value="1">Disconnected</option>
 | 
			
		||||
		<option value="2">Always</option>
 | 
			
		||||
		<option value="3">Never (not recommended)</option></select><br>
 | 
			
		||||
			<option value="0">No connection after boot</option>
 | 
			
		||||
			<option value="1">Disconnected</option>
 | 
			
		||||
			<option value="2">Always</option>
 | 
			
		||||
			<option value="3">Never (not recommended)</option>
 | 
			
		||||
			<option value="4">Temporary (no connection after boot)</option>
 | 
			
		||||
		</select><br>
 | 
			
		||||
		AP IP: <span class="sip"> Not active </span><br>
 | 
			
		||||
		<h3>Experimental</h3>
 | 
			
		||||
		Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
 | 
			
		||||
| 
						 | 
				
			
			@ -241,6 +243,7 @@ Static subnet mask:<br>
 | 
			
		|||
				<option value="0">None</option>
 | 
			
		||||
				<option value="9">ABC! WLED V43 & compatible</option>
 | 
			
		||||
				<option value="2">ESP32-POE</option>
 | 
			
		||||
				<option value="11">ESP32-POE-WROVER</option>
 | 
			
		||||
				<option value="6">ESP32Deux</option>
 | 
			
		||||
				<option value="7">KIT-VE</option>
 | 
			
		||||
				<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -377,27 +377,27 @@ void updateFSInfo() {
 | 
			
		|||
 | 
			
		||||
//Un-comment any file types you need
 | 
			
		||||
static String getContentType(AsyncWebServerRequest* request, String filename){
 | 
			
		||||
  if(request->hasArg("download")) return "application/octet-stream";
 | 
			
		||||
  else if(filename.endsWith(".htm")) return "text/html";
 | 
			
		||||
  else if(filename.endsWith(".html")) return "text/html";
 | 
			
		||||
  else if(filename.endsWith(".css")) return "text/css";
 | 
			
		||||
  else if(filename.endsWith(".js")) return "application/javascript";
 | 
			
		||||
  else if(filename.endsWith(".json")) return "application/json";
 | 
			
		||||
  else if(filename.endsWith(".png")) return "image/png";
 | 
			
		||||
  else if(filename.endsWith(".gif")) return "image/gif";
 | 
			
		||||
  else if(filename.endsWith(".jpg")) return "image/jpeg";
 | 
			
		||||
  else if(filename.endsWith(".ico")) return "image/x-icon";
 | 
			
		||||
//  else if(filename.endsWith(".xml")) return "text/xml";
 | 
			
		||||
//  else if(filename.endsWith(".pdf")) return "application/x-pdf";
 | 
			
		||||
//  else if(filename.endsWith(".zip")) return "application/x-zip";
 | 
			
		||||
//  else if(filename.endsWith(".gz")) return "application/x-gzip";
 | 
			
		||||
  if(request->hasArg(F("download")))     return SET_F("application/octet-stream");
 | 
			
		||||
  else if(filename.endsWith(F(".htm")))  return SET_F("text/html");
 | 
			
		||||
  else if(filename.endsWith(F(".html"))) return SET_F("text/html");
 | 
			
		||||
  else if(filename.endsWith(F(".css")))  return SET_F("text/css");
 | 
			
		||||
  else if(filename.endsWith(F(".js")))   return SET_F("application/javascript");
 | 
			
		||||
  else if(filename.endsWith(F(".json"))) return SET_F("application/json");
 | 
			
		||||
  else if(filename.endsWith(F(".png")))  return SET_F("image/png");
 | 
			
		||||
  else if(filename.endsWith(F(".gif")))  return SET_F("image/gif");
 | 
			
		||||
  else if(filename.endsWith(F(".jpg")))  return SET_F("image/jpeg");
 | 
			
		||||
  else if(filename.endsWith(F(".ico")))  return SET_F("image/x-icon");
 | 
			
		||||
//  else if(filename.endsWith(F(".xml")))   return SET_F("text/xml");
 | 
			
		||||
//  else if(filename.endsWith(F(".pdf")))   return SET_F("application/x-pdf");
 | 
			
		||||
//  else if(filename.endsWith(F(".zip")))   return SET_F("application/x-zip");
 | 
			
		||||
//  else if(filename.endsWith(F(".gz")))    return SET_F("application/x-gzip");
 | 
			
		||||
  return "text/plain";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool handleFileRead(AsyncWebServerRequest* request, String path){
 | 
			
		||||
  DEBUG_PRINTLN("WS FileRead: " + path);
 | 
			
		||||
  if(path.endsWith("/")) path += "index.htm";
 | 
			
		||||
  if(path.indexOf("sec") > -1) return false;
 | 
			
		||||
  if(path.indexOf(F("sec")) > -1) return false;
 | 
			
		||||
  String contentType = getContentType(request, path);
 | 
			
		||||
  /*String pathWithGz = path + ".gz";
 | 
			
		||||
  if(WLED_FS.exists(pathWithGz)){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -470,6 +470,19 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  JsonObject wifi = root[F("wifi")];
 | 
			
		||||
  if (!wifi.isNull()) {
 | 
			
		||||
    bool apMode = getBoolVal(wifi[F("ap")], apActive);
 | 
			
		||||
    if (!apActive && apMode) WLED::instance().initAP();  // start AP mode immediately
 | 
			
		||||
    else if (apActive && !apMode) { // stop AP mode immediately
 | 
			
		||||
      dnsServer.stop();
 | 
			
		||||
      WiFi.softAPdisconnect(true);
 | 
			
		||||
      apActive = false;
 | 
			
		||||
    }
 | 
			
		||||
    //bool restart = wifi[F("restart")] | false;
 | 
			
		||||
    //if (restart) forceReconnect = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  stateUpdated(callMode);
 | 
			
		||||
  if (presetToRestore) currentPreset = presetToRestore;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -611,7 +624,7 @@ void serializeInfo(JsonObject root)
 | 
			
		|||
  root[F("vid")] = VERSION;
 | 
			
		||||
  root[F("cn")] = F(WLED_CODENAME);
 | 
			
		||||
 | 
			
		||||
  JsonObject leds = root.createNestedObject("leds");
 | 
			
		||||
  JsonObject leds = root.createNestedObject(F("leds"));
 | 
			
		||||
  leds[F("count")] = strip.getLengthTotal();
 | 
			
		||||
  leds[F("pwr")] = BusManager::currentMilliamps();
 | 
			
		||||
  leds["fps"] = strip.getFps();
 | 
			
		||||
| 
						 | 
				
			
			@ -622,7 +635,7 @@ void serializeInfo(JsonObject root)
 | 
			
		|||
 | 
			
		||||
  #ifndef WLED_DISABLE_2D
 | 
			
		||||
  if (strip.isMatrix) {
 | 
			
		||||
    JsonObject matrix = leds.createNestedObject("matrix");
 | 
			
		||||
    JsonObject matrix = leds.createNestedObject(F("matrix"));
 | 
			
		||||
    matrix["w"] = Segment::maxWidth;
 | 
			
		||||
    matrix["h"] = Segment::maxHeight;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -702,7 +715,7 @@ void serializeInfo(JsonObject root)
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  JsonObject wifi_info = root.createNestedObject("wifi");
 | 
			
		||||
  JsonObject wifi_info = root.createNestedObject(F("wifi"));
 | 
			
		||||
  wifi_info[F("bssid")] = WiFi.BSSIDstr();
 | 
			
		||||
  int qrssi = WiFi.RSSI();
 | 
			
		||||
  wifi_info[F("rssi")] = qrssi;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,6 +123,16 @@ const ethernet_settings ethernetBoards[] = {
 | 
			
		|||
    18,                   // eth_mdio,
 | 
			
		||||
    ETH_PHY_LAN8720,      // eth_type,
 | 
			
		||||
    ETH_CLOCK_GPIO17_OUT  // eth_clk_mode
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ESP32-POE-WROVER
 | 
			
		||||
  {
 | 
			
		||||
    0,                    // eth_address,
 | 
			
		||||
    12,                   // eth_power,
 | 
			
		||||
    23,                   // eth_mdc,
 | 
			
		||||
    18,                   // eth_mdio,
 | 
			
		||||
    ETH_PHY_LAN8720,      // eth_type,
 | 
			
		||||
    ETH_CLOCK_GPIO0_OUT   // eth_clk_mode
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,7 +170,7 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USERMOD_KLIPPER_PERCENTAGE
 | 
			
		||||
  #include "..\usermods\usermod_v2_klipper_percentage\usermod_v2_klipper_percentage.h"
 | 
			
		||||
  #include "../usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USERMOD_BOBLIGHT
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,8 @@ void WLED::reset()
 | 
			
		|||
 | 
			
		||||
void WLED::loop()
 | 
			
		||||
{
 | 
			
		||||
  static uint32_t      lastHeap = UINT32_MAX;
 | 
			
		||||
  static unsigned long heapTime = 0;
 | 
			
		||||
  #ifdef WLED_DEBUG
 | 
			
		||||
  static unsigned long lastRun = 0;
 | 
			
		||||
  unsigned long        loopMillis = millis();
 | 
			
		||||
| 
						 | 
				
			
			@ -151,6 +153,21 @@ void WLED::loop()
 | 
			
		|||
    createEditHandler(false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // reconnect WiFi to clear stale allocations if heap gets too low
 | 
			
		||||
  if (millis() - heapTime > 15000) {
 | 
			
		||||
    uint32_t heap = ESP.getFreeHeap();
 | 
			
		||||
    if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) {
 | 
			
		||||
      DEBUG_PRINT(F("Heap too low! ")); DEBUG_PRINTLN(heap);
 | 
			
		||||
      forceReconnect = true;
 | 
			
		||||
      strip.resetSegments(); // remove all but one segments from memory
 | 
			
		||||
    } else if (heap < MIN_HEAP_SIZE) {
 | 
			
		||||
      DEBUG_PRINTLN(F("Heap low, purging segments."));
 | 
			
		||||
      strip.purgeSegments();
 | 
			
		||||
    }
 | 
			
		||||
    lastHeap = heap;
 | 
			
		||||
    heapTime = millis();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //LED settings have been saved, re-init busses
 | 
			
		||||
  //This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
 | 
			
		||||
  if (doInitBusses) {
 | 
			
		||||
| 
						 | 
				
			
			@ -386,7 +403,7 @@ void WLED::setup()
 | 
			
		|||
  //DEBUG_PRINT(F("LEDs inited. heap usage ~"));
 | 
			
		||||
  //DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
 | 
			
		||||
 | 
			
		||||
#ifdef WLED_DEBUG
 | 
			
		||||
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
 | 
			
		||||
  pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin
 | 
			
		||||
| 
						 | 
				
			
			@ -891,8 +908,6 @@ void WLED::handleConnection()
 | 
			
		|||
{
 | 
			
		||||
  static bool scanDone = true;
 | 
			
		||||
  static byte stacO = 0;
 | 
			
		||||
  static uint32_t lastHeap = UINT32_MAX;
 | 
			
		||||
  static unsigned long heapTime = 0;
 | 
			
		||||
  unsigned long now = millis();
 | 
			
		||||
  const bool wifiConfigured = WLED_WIFI_CONFIGURED;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -911,21 +926,6 @@ void WLED::handleConnection()
 | 
			
		|||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // reconnect WiFi to clear stale allocations if heap gets too low
 | 
			
		||||
  if (now - heapTime > 5000) {
 | 
			
		||||
    uint32_t heap = ESP.getFreeHeap();
 | 
			
		||||
    if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) {
 | 
			
		||||
      DEBUG_PRINT(F("Heap too low! "));
 | 
			
		||||
      DEBUG_PRINTLN(heap);
 | 
			
		||||
      forceReconnect = true;
 | 
			
		||||
      strip.resetSegments();
 | 
			
		||||
    } else if (heap < MIN_HEAP_SIZE) {
 | 
			
		||||
      strip.purgeSegments();
 | 
			
		||||
    }
 | 
			
		||||
    lastHeap = heap;
 | 
			
		||||
    heapTime = now;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  byte stac = 0;
 | 
			
		||||
  if (apActive) {
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
| 
						 | 
				
			
			@ -974,8 +974,19 @@ void WLED::handleConnection()
 | 
			
		|||
      initConnection();
 | 
			
		||||
    }
 | 
			
		||||
    if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
 | 
			
		||||
      DEBUG_PRINTLN(F("Not connected AP."));
 | 
			
		||||
      initAP();
 | 
			
		||||
      if (!(apBehavior == AP_BEHAVIOR_TEMPORARY && now > WLED_AP_TIMEOUT)) {
 | 
			
		||||
        DEBUG_PRINTLN(F("Not connected AP."));
 | 
			
		||||
        initAP();  // start AP only within first 5min
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (apActive && apBehavior == AP_BEHAVIOR_TEMPORARY && now > WLED_AP_TIMEOUT && stac == 0) { // disconnect AP after 5min if no clients connected
 | 
			
		||||
      // if AP was enabled more than 10min after boot or if client was connected more than 10min after boot do not disconnect AP mode
 | 
			
		||||
      if (now < 2*WLED_AP_TIMEOUT) {
 | 
			
		||||
        dnsServer.stop();
 | 
			
		||||
        WiFi.softAPdisconnect(true);
 | 
			
		||||
        apActive = false;
 | 
			
		||||
        DEBUG_PRINTLN(F("Temporary AP disabled."));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else if (!interfacesInited) { //newly connected
 | 
			
		||||
    DEBUG_PRINTLN();
 | 
			
		||||
| 
						 | 
				
			
			@ -996,7 +1007,7 @@ void WLED::handleConnection()
 | 
			
		|||
      dnsServer.stop();
 | 
			
		||||
      WiFi.softAPdisconnect(true);
 | 
			
		||||
      apActive = false;
 | 
			
		||||
      DEBUG_PRINTLN(F("Access point disabled (handle)."));
 | 
			
		||||
      DEBUG_PRINTLN(F("Access point disabled (connected)."));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
// version code in format yymmddb (b = daily build)
 | 
			
		||||
#define VERSION 2401140
 | 
			
		||||
#define VERSION 2401270
 | 
			
		||||
 | 
			
		||||
//uncomment this if you have a "my_config.h" file you'd like to use
 | 
			
		||||
//#define WLED_USE_MY_CONFIG
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -532,18 +532,18 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
 | 
			
		|||
  const String& url = request->url();
 | 
			
		||||
 | 
			
		||||
  if (url.indexOf("sett") >= 0) {
 | 
			
		||||
    if      (url.indexOf(".js")  > 0) subPage = SUBPAGE_JS;
 | 
			
		||||
    else if (url.indexOf(".css") > 0) subPage = SUBPAGE_CSS;
 | 
			
		||||
    else if (url.indexOf("wifi") > 0) subPage = SUBPAGE_WIFI;
 | 
			
		||||
    else if (url.indexOf("leds") > 0) subPage = SUBPAGE_LEDS;
 | 
			
		||||
    else if (url.indexOf("ui")   > 0) subPage = SUBPAGE_UI;
 | 
			
		||||
    else if (url.indexOf("sync") > 0) subPage = SUBPAGE_SYNC;
 | 
			
		||||
    else if (url.indexOf("time") > 0) subPage = SUBPAGE_TIME;
 | 
			
		||||
    else if (url.indexOf("sec")  > 0) subPage = SUBPAGE_SEC;
 | 
			
		||||
    else if (url.indexOf("dmx")  > 0) subPage = SUBPAGE_DMX;
 | 
			
		||||
    else if (url.indexOf("um")   > 0) subPage = SUBPAGE_UM;
 | 
			
		||||
    else if (url.indexOf("2D")   > 0) subPage = SUBPAGE_2D;
 | 
			
		||||
    else if (url.indexOf("lock") > 0) subPage = SUBPAGE_LOCK;
 | 
			
		||||
    if      (url.indexOf(F(".js"))  > 0) subPage = SUBPAGE_JS;
 | 
			
		||||
    else if (url.indexOf(F(".css")) > 0) subPage = SUBPAGE_CSS;
 | 
			
		||||
    else if (url.indexOf(F("wifi")) > 0) subPage = SUBPAGE_WIFI;
 | 
			
		||||
    else if (url.indexOf(F("leds")) > 0) subPage = SUBPAGE_LEDS;
 | 
			
		||||
    else if (url.indexOf(F("ui"))   > 0) subPage = SUBPAGE_UI;
 | 
			
		||||
    else if (url.indexOf(  "sync")  > 0) subPage = SUBPAGE_SYNC;
 | 
			
		||||
    else if (url.indexOf(  "time")  > 0) subPage = SUBPAGE_TIME;
 | 
			
		||||
    else if (url.indexOf(F("sec"))  > 0) subPage = SUBPAGE_SEC;
 | 
			
		||||
    else if (url.indexOf(  "dmx")   > 0) subPage = SUBPAGE_DMX;
 | 
			
		||||
    else if (url.indexOf(  "um")    > 0) subPage = SUBPAGE_UM;
 | 
			
		||||
    else if (url.indexOf(  "2D")    > 0) subPage = SUBPAGE_2D;
 | 
			
		||||
    else if (url.indexOf(F("lock")) > 0) subPage = SUBPAGE_LOCK;
 | 
			
		||||
  }
 | 
			
		||||
  else if (url.indexOf("/update") >= 0) subPage = SUBPAGE_UPDATE; // update page, for PIN check
 | 
			
		||||
  //else if (url.indexOf("/edit")   >= 0) subPage = 10;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,8 +157,8 @@ void appendGPIOinfo() {
 | 
			
		|||
  oappend(SET_F(",2")); // DMX hardcoded pin
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #ifdef WLED_DEBUG
 | 
			
		||||
  oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10));// debug output (TX) pin
 | 
			
		||||
  #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
 | 
			
		||||
  oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10)); // debug output (TX) pin
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  //Note: Using pin 3 (RX) disables Adalight / Serial JSON
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue