kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			
							rodzic
							
								
									e80594d61d
								
							
						
					
					
						commit
						4d89ed701d
					
				
							
								
								
									
										261
									
								
								wled00/FX.cpp
								
								
								
								
							
							
						
						
									
										261
									
								
								wled00/FX.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -388,41 +388,12 @@ uint16_t WS2812FX::mode_rainbow_cycle(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * theater chase function
 | 
			
		||||
 */
 | 
			
		||||
uint16_t WS2812FX::theater_chase(uint32_t color1, uint32_t color2, bool do_palette) {
 | 
			
		||||
  byte gap = 2 + ((255 - SEGMENT.intensity) >> 5);
 | 
			
		||||
  uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*2;
 | 
			
		||||
  uint32_t it = now / cycleTime;
 | 
			
		||||
  if (it != SEGENV.step) //new color
 | 
			
		||||
  {
 | 
			
		||||
    SEGENV.aux0 = (SEGENV.aux0 +1) % gap;
 | 
			
		||||
    SEGENV.step = it;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  for(uint16_t i = 0; i < SEGLEN; i++) {
 | 
			
		||||
    if((i % gap) == SEGENV.aux0) {
 | 
			
		||||
      if (do_palette)
 | 
			
		||||
      {
 | 
			
		||||
        setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
      } else {
 | 
			
		||||
        setPixelColor(i, color1);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      setPixelColor(i, color2);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Theatre-style crawling lights.
 | 
			
		||||
 * Inspired by the Adafruit examples.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t WS2812FX::mode_theater_chase(void) {
 | 
			
		||||
  return theater_chase(SEGCOLOR(0), SEGCOLOR(1), true);
 | 
			
		||||
  return running(SEGCOLOR(0), SEGCOLOR(1), true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -431,7 +402,7 @@ uint16_t WS2812FX::mode_theater_chase(void) {
 | 
			
		|||
 * Inspired by the Adafruit examples.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t WS2812FX::mode_theater_chase_rainbow(void) {
 | 
			
		||||
  return theater_chase(color_wheel(SEGENV.step), SEGCOLOR(1), false);
 | 
			
		||||
  return running(color_wheel(SEGENV.step), SEGCOLOR(1), true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -976,29 +947,27 @@ uint16_t WS2812FX::mode_chase_flash_random(void) {
 | 
			
		|||
/*
 | 
			
		||||
 * Alternating pixels running function.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t WS2812FX::running(uint32_t color1, uint32_t color2) {
 | 
			
		||||
  uint8_t pxw = 1 + (SEGMENT.intensity >> 5);
 | 
			
		||||
  uint32_t cycleTime = 35 + (255 - SEGMENT.speed);
 | 
			
		||||
uint16_t WS2812FX::running(uint32_t color1, uint32_t color2, bool theatre) {
 | 
			
		||||
  uint8_t width = (theatre ? 3 : 1) + (SEGMENT.intensity >> 4);  // window
 | 
			
		||||
  uint32_t cycleTime = 50 + (255 - SEGMENT.speed);
 | 
			
		||||
  uint32_t it = now / cycleTime;
 | 
			
		||||
  if (SEGMENT.speed == 0) it = 0;
 | 
			
		||||
 | 
			
		||||
  bool usePalette = color1 == SEGCOLOR(0);
 | 
			
		||||
  
 | 
			
		||||
  for(uint16_t i = 0; i < SEGLEN; i++) {
 | 
			
		||||
    if((i + SEGENV.aux0) % (pxw*2) < pxw) {
 | 
			
		||||
      if (color1 == SEGCOLOR(0))
 | 
			
		||||
      {
 | 
			
		||||
        setPixelColor(SEGLEN -i -1, color_from_palette(SEGLEN -i -1, true, PALETTE_SOLID_WRAP, 0));
 | 
			
		||||
      } else
 | 
			
		||||
      {
 | 
			
		||||
        setPixelColor(SEGLEN -i -1, color1);
 | 
			
		||||
      }
 | 
			
		||||
    uint32_t col = color2;
 | 
			
		||||
    if (usePalette) color1 = color_from_palette(i, true, PALETTE_SOLID_WRAP, 0);
 | 
			
		||||
    if (theatre) {
 | 
			
		||||
      if ((i % width) == SEGENV.aux0) col = color1;
 | 
			
		||||
    } else {
 | 
			
		||||
      setPixelColor(SEGLEN -i -1, color2);
 | 
			
		||||
      int8_t pos = (i % (width<<1));
 | 
			
		||||
      if ((pos < SEGENV.aux0-width) || ((pos >= SEGENV.aux0) && (pos < SEGENV.aux0+width))) col = color1;
 | 
			
		||||
    }
 | 
			
		||||
    setPixelColor(i,col);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (it != SEGENV.step )
 | 
			
		||||
  {
 | 
			
		||||
    SEGENV.aux0 = (SEGENV.aux0 +1) % (pxw*2);
 | 
			
		||||
    SEGENV.aux0 = (SEGENV.aux0 +1) % (theatre ? width : (width<<1));
 | 
			
		||||
    SEGENV.step = it;
 | 
			
		||||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
| 
						 | 
				
			
			@ -1247,44 +1216,19 @@ uint16_t WS2812FX::mode_loading(void) {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
//American Police Light with all LEDs Red and Blue 
 | 
			
		||||
uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2, bool all)
 | 
			
		||||
uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2, uint16_t width)
 | 
			
		||||
{
 | 
			
		||||
  uint16_t counter = now * ((SEGMENT.speed >> 2) +1);
 | 
			
		||||
  uint16_t idexR = (counter * SEGLEN) >> 16;
 | 
			
		||||
  if (idexR >= SEGLEN) idexR = 0;
 | 
			
		||||
 | 
			
		||||
  uint16_t topindex = SEGLEN >> 1;
 | 
			
		||||
  uint16_t idexB = (idexR > topindex) ? idexR - topindex : idexR + topindex;
 | 
			
		||||
  if (SEGENV.call == 0) SEGENV.aux0 = idexR;
 | 
			
		||||
  if (idexB >= SEGLEN) idexB = 0; //otherwise overflow on odd number of LEDs
 | 
			
		||||
 | 
			
		||||
  if (all) { //different algo, ensuring immediate fill
 | 
			
		||||
    if (idexB > idexR) {
 | 
			
		||||
      fill(color2);
 | 
			
		||||
      for (uint16_t i = idexR; i < idexB; i++) setPixelColor(i, color1);
 | 
			
		||||
    } else {
 | 
			
		||||
      fill(color1);
 | 
			
		||||
      for (uint16_t i = idexB; i < idexR; i++) setPixelColor(i, color2);
 | 
			
		||||
    } 
 | 
			
		||||
  } else { //regular dot-only mode
 | 
			
		||||
    uint8_t size = 1 + (SEGMENT.intensity >> 3);
 | 
			
		||||
    if (size > SEGLEN/2) size = 1+ SEGLEN/2;
 | 
			
		||||
    for (uint8_t i=0; i <= size; i++) {
 | 
			
		||||
      setPixelColor(idexR+i, color1);
 | 
			
		||||
      setPixelColor(idexB+i, color2);
 | 
			
		||||
    }
 | 
			
		||||
    if (SEGENV.aux0 != idexR) {
 | 
			
		||||
      uint8_t gap = (SEGENV.aux0 < idexR)? idexR - SEGENV.aux0:SEGLEN - SEGENV.aux0 + idexR;
 | 
			
		||||
      for (uint8_t i = 0; i <= gap ; i++) {
 | 
			
		||||
        if ((idexR - i) < 0) idexR = SEGLEN-1 + i;
 | 
			
		||||
        if ((idexB - i) < 0) idexB = SEGLEN-1 + i;
 | 
			
		||||
        setPixelColor(idexR-i, color1);
 | 
			
		||||
        setPixelColor(idexB-i, color2);
 | 
			
		||||
      }
 | 
			
		||||
      SEGENV.aux0 = idexR;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  uint16_t delay = 1 + (FRAMETIME<<3) / SEGLEN;  // longer segments should change faster
 | 
			
		||||
  uint32_t it = now / map(SEGMENT.speed, 0, 255, delay<<4, delay);
 | 
			
		||||
  uint16_t offset = it % SEGLEN;
 | 
			
		||||
  
 | 
			
		||||
  if (!width) width = 1;
 | 
			
		||||
  for (uint16_t i = 0; i < width; i++) {
 | 
			
		||||
    uint16_t indexR = (offset + i) % SEGLEN;
 | 
			
		||||
    uint16_t indexB = (offset + i + (SEGLEN>>1)) % SEGLEN;
 | 
			
		||||
    setPixelColor(indexR, color1);
 | 
			
		||||
    setPixelColor(indexB, color2);
 | 
			
		||||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1292,7 +1236,7 @@ uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2, bool all)
 | 
			
		|||
//American Police Light with all LEDs Red and Blue 
 | 
			
		||||
uint16_t WS2812FX::mode_police_all()
 | 
			
		||||
{
 | 
			
		||||
  return police_base(RED, BLUE, true);
 | 
			
		||||
  return police_base(RED, BLUE, (SEGLEN>>1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1300,15 +1244,15 @@ uint16_t WS2812FX::mode_police_all()
 | 
			
		|||
uint16_t WS2812FX::mode_police()
 | 
			
		||||
{
 | 
			
		||||
  fill(SEGCOLOR(1));
 | 
			
		||||
 | 
			
		||||
  return police_base(RED, BLUE, false);
 | 
			
		||||
  return police_base(RED, BLUE, ((SEGLEN*(SEGMENT.intensity+1))>>9)); // max width is half the strip
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Police All with custom colors
 | 
			
		||||
uint16_t WS2812FX::mode_two_areas()
 | 
			
		||||
{
 | 
			
		||||
  return police_base(SEGCOLOR(0), SEGCOLOR(1), true);
 | 
			
		||||
  fill(SEGCOLOR(2));
 | 
			
		||||
  return police_base(SEGCOLOR(0), SEGCOLOR(1), ((SEGLEN*(SEGMENT.intensity+1))>>9)); // max width is half the strip
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1318,7 +1262,7 @@ uint16_t WS2812FX::mode_two_dots()
 | 
			
		|||
  fill(SEGCOLOR(2));
 | 
			
		||||
  uint32_t color2 = (SEGCOLOR(1) == SEGCOLOR(2)) ? SEGCOLOR(0) : SEGCOLOR(1);
 | 
			
		||||
 | 
			
		||||
  return police_base(SEGCOLOR(0), color2, false);
 | 
			
		||||
  return police_base(SEGCOLOR(0), color2, ((SEGLEN*(SEGMENT.intensity+1))>>9)); // max width is half the strip
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1326,21 +1270,20 @@ uint16_t WS2812FX::mode_two_dots()
 | 
			
		|||
 * Tricolor chase function
 | 
			
		||||
 */
 | 
			
		||||
uint16_t WS2812FX::tricolor_chase(uint32_t color1, uint32_t color2) {
 | 
			
		||||
  uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*2;
 | 
			
		||||
  uint32_t it = now / cycleTime;
 | 
			
		||||
  uint8_t width = (1 + SEGMENT.intensity/32) * 3; //value of 1-8 for each colour
 | 
			
		||||
  uint8_t index = it % width;
 | 
			
		||||
  uint32_t cycleTime = 50 + ((255 - SEGMENT.speed)<<1);
 | 
			
		||||
  uint32_t it = now / cycleTime;  // iterator
 | 
			
		||||
  uint8_t width = (1 + (SEGMENT.intensity>>4)); // value of 1-16 for each colour
 | 
			
		||||
  uint8_t index = it % (width*3);
 | 
			
		||||
  
 | 
			
		||||
  for(uint16_t i = 0; i < SEGLEN; i++, index++) {
 | 
			
		||||
    if(index > width-1) index = 0;
 | 
			
		||||
  for (uint16_t i = 0; i < SEGLEN; i++, index++) {
 | 
			
		||||
    if (index > (width*3)-1) index = 0;
 | 
			
		||||
 | 
			
		||||
    uint32_t color = color1;
 | 
			
		||||
    if(index > width*2/3-1) color = color_from_palette(i, true, PALETTE_SOLID_WRAP, 1);
 | 
			
		||||
    else if(index > width/3-1) color = color2;
 | 
			
		||||
    if (index > (width<<1)-1) color = color_from_palette(i, true, PALETTE_SOLID_WRAP, 1);
 | 
			
		||||
    else if (index > width-1) color = color2;
 | 
			
		||||
 | 
			
		||||
    setPixelColor(SEGLEN - i -1, color);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1548,7 +1491,7 @@ uint16_t WS2812FX::mode_random_chase(void)
 | 
			
		|||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//7 bytes
 | 
			
		||||
typedef struct Oscillator {
 | 
			
		||||
  int16_t pos;
 | 
			
		||||
  int8_t  size;
 | 
			
		||||
| 
						 | 
				
			
			@ -1780,7 +1723,7 @@ uint16_t WS2812FX::mode_fire_2012()
 | 
			
		|||
    // Step 1.  Cool down every cell a little
 | 
			
		||||
    for (uint16_t i = 0; i < SEGLEN; i++) {
 | 
			
		||||
      uint8_t temp = qsub8(heat[i], random8(0, (((20 + SEGMENT.speed /3) * 10) / SEGLEN) + 2));
 | 
			
		||||
      heat[i] = (temp==0 && i<ignition) ? 2 : temp; // prevent ignition area from becoming black
 | 
			
		||||
      heat[i] = (temp==0 && i<ignition) ? 16 : temp; // prevent ignition area from becoming black
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
 | 
			
		||||
| 
						 | 
				
			
			@ -1994,7 +1937,7 @@ uint16_t WS2812FX::mode_colortwinkle()
 | 
			
		|||
    
 | 
			
		||||
    if (fadeUp) {
 | 
			
		||||
      CRGB incrementalColor = fastled_col;
 | 
			
		||||
      incrementalColor.nscale8_video( fadeUpAmount);
 | 
			
		||||
      incrementalColor.nscale8_video(fadeUpAmount);
 | 
			
		||||
      fastled_col += incrementalColor;
 | 
			
		||||
 | 
			
		||||
      if (fastled_col.red == 255 || fastled_col.green == 255 || fastled_col.blue == 255) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2002,24 +1945,21 @@ uint16_t WS2812FX::mode_colortwinkle()
 | 
			
		|||
      }
 | 
			
		||||
      setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
 | 
			
		||||
 | 
			
		||||
      if (col_to_crgb(getPixelColor(i)) == prev) //fix "stuck" pixels
 | 
			
		||||
      {
 | 
			
		||||
      if (col_to_crgb(getPixelColor(i)) == prev) {  //fix "stuck" pixels
 | 
			
		||||
        fastled_col += fastled_col;
 | 
			
		||||
        setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      fastled_col.nscale8( 255 - fadeDownAmount);
 | 
			
		||||
      fastled_col.nscale8(255 - fadeDownAmount);
 | 
			
		||||
      setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (uint16_t j = 0; j <= SEGLEN / 50; j++)
 | 
			
		||||
  {
 | 
			
		||||
  for (uint16_t j = 0; j <= SEGLEN / 50; j++) {
 | 
			
		||||
    if (random8() <= SEGMENT.intensity) {
 | 
			
		||||
      for (uint8_t times = 0; times < 5; times++) //attempt to spawn a new pixel 5 times
 | 
			
		||||
      {
 | 
			
		||||
      for (uint8_t times = 0; times < 5; times++) { //attempt to spawn a new pixel 5 times
 | 
			
		||||
        int i = random16(SEGLEN);
 | 
			
		||||
        if(getPixelColor(i) == 0) {
 | 
			
		||||
        if (getPixelColor(i) == 0) {
 | 
			
		||||
          fastled_col = ColorFromPalette(currentPalette, random8(), 64, NOBLEND);
 | 
			
		||||
          uint16_t index = i >> 3;
 | 
			
		||||
          uint8_t  bitNum = i & 0x07;
 | 
			
		||||
| 
						 | 
				
			
			@ -2170,10 +2110,14 @@ typedef struct Ripple {
 | 
			
		|||
  uint16_t pos;
 | 
			
		||||
} ripple;
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define MAX_RIPPLES   56
 | 
			
		||||
#else
 | 
			
		||||
  #define MAX_RIPPLES  100
 | 
			
		||||
#endif
 | 
			
		||||
uint16_t WS2812FX::ripple_base(bool rainbow)
 | 
			
		||||
{
 | 
			
		||||
  uint16_t maxRipples = 1 + (SEGLEN >> 2);
 | 
			
		||||
  if (maxRipples > 100) maxRipples = 100;
 | 
			
		||||
  uint16_t maxRipples = min(1 + (SEGLEN >> 2), MAX_RIPPLES);  // 56 max for 18 segment ESP8266
 | 
			
		||||
  uint16_t dataSize = sizeof(ripple) * maxRipples;
 | 
			
		||||
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
| 
						 | 
				
			
			@ -2241,6 +2185,7 @@ uint16_t WS2812FX::ripple_base(bool rainbow)
 | 
			
		|||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
#undef MAX_RIPPLES
 | 
			
		||||
 | 
			
		||||
uint16_t WS2812FX::mode_ripple(void) {
 | 
			
		||||
  return ripple_base(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -2541,7 +2486,6 @@ uint16_t WS2812FX::mode_spots_fade()
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
//each needs 12 bytes
 | 
			
		||||
//Spark type is used for popcorn and 1D fireworks
 | 
			
		||||
typedef struct Ball {
 | 
			
		||||
  unsigned long lastBounceTime;
 | 
			
		||||
  float impactVelocity;
 | 
			
		||||
| 
						 | 
				
			
			@ -2651,7 +2595,7 @@ uint16_t WS2812FX::mode_sinelon_dual(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
uint16_t WS2812FX::mode_sinelon_rainbow(void) {
 | 
			
		||||
  return sinelon_base(true, true);
 | 
			
		||||
  return sinelon_base(false, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2670,7 +2614,7 @@ uint16_t WS2812FX::mode_glitter()
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//each needs 12 bytes
 | 
			
		||||
//each needs 11 bytes
 | 
			
		||||
//Spark type is used for popcorn, 1D fireworks, and drip
 | 
			
		||||
typedef struct Spark {
 | 
			
		||||
  float pos;
 | 
			
		||||
| 
						 | 
				
			
			@ -2685,7 +2629,7 @@ typedef struct Spark {
 | 
			
		|||
*/
 | 
			
		||||
uint16_t WS2812FX::mode_popcorn(void) {
 | 
			
		||||
  //allocate segment data
 | 
			
		||||
  uint16_t maxNumPopcorn = 24; 
 | 
			
		||||
  uint16_t maxNumPopcorn = 22; // max 22 on 18 segment ESP8266
 | 
			
		||||
  uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			@ -2744,7 +2688,7 @@ uint16_t WS2812FX::candle(bool multi)
 | 
			
		|||
  if (multi)
 | 
			
		||||
  {
 | 
			
		||||
    //allocate segment data
 | 
			
		||||
    uint16_t dataSize = (SEGLEN -1) *3;
 | 
			
		||||
    uint16_t dataSize = (SEGLEN -1) *3; // max length of segment on 18 segment ESP8266 is 75 pixels
 | 
			
		||||
    if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2831,9 +2775,14 @@ uint16_t WS2812FX::mode_candle_multi()
 | 
			
		|||
/ based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/
 | 
			
		||||
/ Speed sets frequency of new starbursts, intensity is the intensity of the burst
 | 
			
		||||
*/
 | 
			
		||||
#define STARBURST_MAX_FRAG 12
 | 
			
		||||
 | 
			
		||||
//each needs 64 byte
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define STARBURST_MAX_FRAG   4
 | 
			
		||||
  #define STARBURST_MAX_STARS  6
 | 
			
		||||
#else
 | 
			
		||||
  #define STARBURST_MAX_FRAG  10
 | 
			
		||||
  #define STARBURST_MAX_STARS 11
 | 
			
		||||
#endif
 | 
			
		||||
//each needs 18+STARBURST_MAX_FRAG*4 bytes
 | 
			
		||||
typedef struct particle {
 | 
			
		||||
  CRGB     color;
 | 
			
		||||
  uint32_t birth  =0;
 | 
			
		||||
| 
						 | 
				
			
			@ -2845,7 +2794,7 @@ typedef struct particle {
 | 
			
		|||
 | 
			
		||||
uint16_t WS2812FX::mode_starburst(void) {
 | 
			
		||||
  uint8_t numStars = 1 + (SEGLEN >> 3);
 | 
			
		||||
  if (numStars > 15) numStars = 15;
 | 
			
		||||
  if (numStars > STARBURST_MAX_STARS) numStars = STARBURST_MAX_STARS; // 11 * 58 * 32 = 19k (ESP32), 6 * 34 * 18 = 4k (ESP8266)
 | 
			
		||||
  uint16_t dataSize = sizeof(star) * numStars;
 | 
			
		||||
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
| 
						 | 
				
			
			@ -2946,18 +2895,22 @@ uint16_t WS2812FX::mode_starburst(void) {
 | 
			
		|||
  }
 | 
			
		||||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef STARBURST_MAX_FRAG
 | 
			
		||||
#undef STARBURST_MAX_STARS
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Exploding fireworks effect
 | 
			
		||||
 * adapted from: http://www.anirama.com/1000leds/1d-fireworks/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define MAX_SPARKS 20 // number of fragments
 | 
			
		||||
#else
 | 
			
		||||
  #define MAX_SPARKS 58 // number of fragments
 | 
			
		||||
#endif
 | 
			
		||||
uint16_t WS2812FX::mode_exploding_fireworks(void)
 | 
			
		||||
{
 | 
			
		||||
  //allocate segment data
 | 
			
		||||
  uint16_t numSparks = 2 + (SEGLEN >> 1); 
 | 
			
		||||
  if (numSparks > 80) numSparks = 80;
 | 
			
		||||
  uint16_t numSparks = min(2 + (SEGLEN >> 2), MAX_SPARKS);  // max 58 for 32 segment ESP32, 20 for 18 segment ESP8266
 | 
			
		||||
  uint16_t dataSize = sizeof(spark) * numSparks;
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3052,7 +3005,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
 | 
			
		|||
    SEGENV.aux0--;
 | 
			
		||||
    if (SEGENV.aux0 < 4) {
 | 
			
		||||
      SEGENV.aux0 = 0; //back to flare
 | 
			
		||||
      SEGENV.step = (SEGMENT.intensity > random8()); //decide firing side
 | 
			
		||||
      SEGENV.step = actuallyReverse ^ (SEGMENT.intensity > random8()); //decide firing side
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3060,6 +3013,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
 | 
			
		|||
  
 | 
			
		||||
  return FRAMETIME;  
 | 
			
		||||
}
 | 
			
		||||
#undef MAX_SPARKS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -3069,7 +3023,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
 | 
			
		|||
uint16_t WS2812FX::mode_drip(void)
 | 
			
		||||
{
 | 
			
		||||
  //allocate segment data
 | 
			
		||||
  uint16_t numDrops = 4; 
 | 
			
		||||
  uint8_t numDrops = 4; 
 | 
			
		||||
  uint16_t dataSize = sizeof(spark) * numDrops;
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3077,7 +3031,7 @@ uint16_t WS2812FX::mode_drip(void)
 | 
			
		|||
  
 | 
			
		||||
  Spark* drops = reinterpret_cast<Spark*>(SEGENV.data);
 | 
			
		||||
 | 
			
		||||
  numDrops = 1 + (SEGMENT.intensity >> 6);
 | 
			
		||||
  numDrops = 1 + (SEGMENT.intensity >> 6); // 255>>6 = 3
 | 
			
		||||
 | 
			
		||||
  float gravity = -0.0005 - (SEGMENT.speed/50000.0);
 | 
			
		||||
  gravity *= SEGLEN;
 | 
			
		||||
| 
						 | 
				
			
			@ -3107,13 +3061,13 @@ uint16_t WS2812FX::mode_drip(void)
 | 
			
		|||
      if (drops[j].pos > 0) {              // fall until end of segment
 | 
			
		||||
        drops[j].pos += drops[j].vel;
 | 
			
		||||
        if (drops[j].pos < 0) drops[j].pos = 0;
 | 
			
		||||
        drops[j].vel += gravity;
 | 
			
		||||
        drops[j].vel += gravity;           // gravity is negative
 | 
			
		||||
 | 
			
		||||
        for (uint16_t i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets
 | 
			
		||||
          uint16_t pos = constrain(uint16_t(drops[j].pos) +i, 0, SEGLEN-1); //this is BAD, returns a pos >= SEGLEN occasionally
 | 
			
		||||
          setPixelColor(pos,color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if (drops[j].colIndex > 2) {       // during bounce, some water is on the floor
 | 
			
		||||
          setPixelColor(0,color_blend(SEGCOLOR(0),BLACK,drops[j].col));
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -3142,6 +3096,7 @@ uint16_t WS2812FX::mode_drip(void)
 | 
			
		|||
 * Tetris or Stacking (falling bricks) Effect
 | 
			
		||||
 * by Blaz Kristan (https://github.com/blazoncek, https://blaz.at/home)
 | 
			
		||||
 */
 | 
			
		||||
//12 bytes
 | 
			
		||||
typedef struct Tetris {
 | 
			
		||||
  float    pos;
 | 
			
		||||
  float    speed;
 | 
			
		||||
| 
						 | 
				
			
			@ -3163,8 +3118,8 @@ uint16_t WS2812FX::mode_tetrix(void) {
 | 
			
		|||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (SEGENV.step == 0) {             //init
 | 
			
		||||
    drop->speed = 0.0238 * (SEGMENT.speed ? (SEGMENT.speed>>3)+1 : random8(6,40)); // set speed
 | 
			
		||||
    drop->pos   = SEGLEN-1;           // start at end of segment
 | 
			
		||||
    drop->speed = 0.0238 * (SEGMENT.speed ? (SEGMENT.speed>>2)+1 : random8(6,64)); // set speed
 | 
			
		||||
    drop->pos   = SEGLEN;             // start at end of segment (no need to subtract 1)
 | 
			
		||||
    drop->col   = color_from_palette(random8(0,15)<<4,false,false,0);     // limit color choices so there is enough HUE gap
 | 
			
		||||
    SEGENV.step = 1;                  // drop state (0 init, 1 forming, 2 falling)
 | 
			
		||||
    SEGENV.aux0 = (SEGMENT.intensity ? (SEGMENT.intensity>>5)+1 : random8(1,5)) * (1+(SEGLEN>>6));  // size of brick
 | 
			
		||||
| 
						 | 
				
			
			@ -3196,13 +3151,17 @@ uint16_t WS2812FX::mode_tetrix(void) {
 | 
			
		|||
/ adapted from https://github.com/atuline/FastLED-Demos/blob/master/plasma/plasma.ino
 | 
			
		||||
*/
 | 
			
		||||
uint16_t WS2812FX::mode_plasma(void) {
 | 
			
		||||
  uint8_t thisPhase = beatsin8(6,-64,64);                       // Setting phase change for a couple of waves.
 | 
			
		||||
  uint8_t thatPhase = beatsin8(7,-64,64);
 | 
			
		||||
  // initialize phases on start
 | 
			
		||||
  if (SEGENV.call == 0) {
 | 
			
		||||
    SEGENV.aux0 = random8(0,2);  // add a bit of randomness
 | 
			
		||||
  }
 | 
			
		||||
  uint8_t thisPhase = beatsin8(6+SEGENV.aux0,-64,64);
 | 
			
		||||
  uint8_t thatPhase = beatsin8(7+SEGENV.aux0,-64,64);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SEGLEN; i++) {   // For each of the LED's in the strand, set color &  brightness based on a wave as follows:
 | 
			
		||||
    uint8_t colorIndex = cubicwave8(((i*(1+ 3*(SEGMENT.speed >> 5)))+(thisPhase)) & 0xFF)/2   // factor=23 // Create a wave and add a phase change and add another wave with its own phase change.
 | 
			
		||||
                             + cos8(((i*(1+ 2*(SEGMENT.speed >> 5)))+(thatPhase)) & 0xFF)/2;  // factor=15 // Hey, you can even change the frequencies if you wish.
 | 
			
		||||
    uint8_t thisBright = qsub8(colorIndex, beatsin8(6,0, (255 - SEGMENT.intensity)|0x01 ));
 | 
			
		||||
    uint8_t colorIndex = cubicwave8((i*(2+ 3*(SEGMENT.speed >> 5))+thisPhase) & 0xFF)/2   // factor=23 // Create a wave and add a phase change and add another wave with its own phase change.
 | 
			
		||||
                             + cos8((i*(1+ 2*(SEGMENT.speed >> 5))+thatPhase) & 0xFF)/2;  // factor=15 // Hey, you can even change the frequencies if you wish.
 | 
			
		||||
    uint8_t thisBright = qsub8(colorIndex, beatsin8(7,0, (128 - (SEGMENT.intensity>>1))));
 | 
			
		||||
    CRGB color = ColorFromPalette(currentPalette, colorIndex, thisBright, LINEARBLEND);
 | 
			
		||||
    setPixelColor(i, color.red, color.green, color.blue);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -3531,7 +3490,7 @@ uint16_t WS2812FX::mode_noisepal(void) {                                    // S
 | 
			
		|||
  uint16_t scale = 15 + (SEGMENT.intensity >> 2); //default was 30
 | 
			
		||||
  //#define scale 30
 | 
			
		||||
 | 
			
		||||
  uint16_t dataSize = sizeof(CRGBPalette16) * 2; //allocate space for 2 Palettes
 | 
			
		||||
  uint16_t dataSize = sizeof(CRGBPalette16) * 2; //allocate space for 2 Palettes (2 * 16 * 3 = 96 bytes)
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
 | 
			
		||||
  CRGBPalette16* palettes = reinterpret_cast<CRGBPalette16*>(SEGENV.data);
 | 
			
		||||
| 
						 | 
				
			
			@ -3644,7 +3603,7 @@ uint16_t WS2812FX::mode_chunchun(void)
 | 
			
		|||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//13 bytes
 | 
			
		||||
typedef struct Spotlight {
 | 
			
		||||
  float speed;
 | 
			
		||||
  uint8_t colorIdx;
 | 
			
		||||
| 
						 | 
				
			
			@ -3661,6 +3620,11 @@ typedef struct Spotlight {
 | 
			
		|||
#define SPOT_TYPE_3X_DOT      4
 | 
			
		||||
#define SPOT_TYPE_4X_DOT      5
 | 
			
		||||
#define SPOT_TYPES_COUNT      6
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define SPOT_MAX_COUNT 17          //Number of simultaneous waves
 | 
			
		||||
#else
 | 
			
		||||
  #define SPOT_MAX_COUNT 49          //Number of simultaneous waves
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Spotlights moving back and forth that cast dancing shadows.
 | 
			
		||||
| 
						 | 
				
			
			@ -3671,7 +3635,7 @@ typedef struct Spotlight {
 | 
			
		|||
 */
 | 
			
		||||
uint16_t WS2812FX::mode_dancing_shadows(void)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, 50);
 | 
			
		||||
  uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, SPOT_MAX_COUNT);  // 49 on 32 segment ESP32, 17 on 18 segment ESP8266
 | 
			
		||||
  bool initialize = SEGENV.aux0 != numSpotlights;
 | 
			
		||||
  SEGENV.aux0 = numSpotlights;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3810,7 +3774,7 @@ uint16_t WS2812FX::mode_washing_machine(void) {
 | 
			
		|||
  Modified, originally by Mark Kriegsman https://gist.github.com/kriegsman/1f7ccbbfa492a73c015e
 | 
			
		||||
*/
 | 
			
		||||
uint16_t WS2812FX::mode_blends(void) {
 | 
			
		||||
  uint16_t dataSize = sizeof(uint32_t) * SEGLEN;
 | 
			
		||||
  uint16_t dataSize = sizeof(uint32_t) * SEGLEN;  // max segment length of 56 pixels on 18 segment ESP8266
 | 
			
		||||
  if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
 | 
			
		||||
  uint32_t* pixels = reinterpret_cast<uint32_t*>(SEGENV.data);
 | 
			
		||||
  uint8_t blendSpeed = map(SEGMENT.intensity, 0, UINT8_MAX, 10, 128);
 | 
			
		||||
| 
						 | 
				
			
			@ -3825,6 +3789,11 @@ uint16_t WS2812FX::mode_blends(void) {
 | 
			
		|||
  return FRAMETIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  TV Simulator
 | 
			
		||||
  Modified and adapted to WLED by Def3nder, based on "Fake TV Light for Engineers" by Phillip Burgess https://learn.adafruit.com/fake-tv-light-for-engineers/arduino-sketch
 | 
			
		||||
*/
 | 
			
		||||
//43 bytes
 | 
			
		||||
typedef struct TvSim {
 | 
			
		||||
  uint32_t totalTime = 0;
 | 
			
		||||
  uint32_t fadeTime  = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -3845,11 +3814,6 @@ typedef struct TvSim {
 | 
			
		|||
  uint16_t pb = 0;
 | 
			
		||||
} tvSim;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  TV Simulator
 | 
			
		||||
  Modified and adapted to WLED by Def3nder, based on "Fake TV Light for Engineers" by Phillip Burgess https://learn.adafruit.com/fake-tv-light-for-engineers/arduino-sketch
 | 
			
		||||
*/
 | 
			
		||||
uint16_t WS2812FX::mode_tv_simulator(void) {
 | 
			
		||||
  uint16_t nr, ng, nb, r, g, b, i, hue;
 | 
			
		||||
  uint8_t  sat, bri, j;
 | 
			
		||||
| 
						 | 
				
			
			@ -3957,10 +3921,15 @@ uint16_t WS2812FX::mode_tv_simulator(void) {
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
//CONFIG
 | 
			
		||||
#define W_MAX_COUNT 20            //Number of simultaneous waves
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define W_MAX_COUNT  9          //Number of simultaneous waves
 | 
			
		||||
#else
 | 
			
		||||
  #define W_MAX_COUNT 20          //Number of simultaneous waves
 | 
			
		||||
#endif
 | 
			
		||||
#define W_MAX_SPEED 6             //Higher number, higher speed
 | 
			
		||||
#define W_WIDTH_FACTOR 6          //Higher number, smaller waves
 | 
			
		||||
 | 
			
		||||
//24 bytes
 | 
			
		||||
class AuroraWave {
 | 
			
		||||
  private:
 | 
			
		||||
    uint16_t ttl;
 | 
			
		||||
| 
						 | 
				
			
			@ -4055,10 +4024,10 @@ uint16_t WS2812FX::mode_aurora(void) {
 | 
			
		|||
 | 
			
		||||
  if(SEGENV.aux0 != SEGMENT.intensity || SEGENV.call == 0) {
 | 
			
		||||
    //Intensity slider changed or first call
 | 
			
		||||
    SEGENV.aux1 = ((float)SEGMENT.intensity / 255) * W_MAX_COUNT;
 | 
			
		||||
    SEGENV.aux1 = map(SEGMENT.intensity, 0, 255, 2, W_MAX_COUNT);
 | 
			
		||||
    SEGENV.aux0 = SEGMENT.intensity;
 | 
			
		||||
 | 
			
		||||
    if(!SEGENV.allocateData(sizeof(AuroraWave) * SEGENV.aux1)) {
 | 
			
		||||
    if(!SEGENV.allocateData(sizeof(AuroraWave) * SEGENV.aux1)) { // 26 on 32 segment ESP32, 9 on 18 segment ESP8266
 | 
			
		||||
      return mode_static(); //allocation failed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										71
									
								
								wled00/FX.h
								
								
								
								
							
							
						
						
									
										71
									
								
								wled00/FX.h
								
								
								
								
							| 
						 | 
				
			
			@ -24,8 +24,6 @@
 | 
			
		|||
  Modified for WLED
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "wled.h"
 | 
			
		||||
 | 
			
		||||
#ifndef WS2812FX_h
 | 
			
		||||
#define WS2812FX_h
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,17 +53,17 @@
 | 
			
		|||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
 | 
			
		||||
  insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
  #define MAX_NUM_SEGMENTS    12
 | 
			
		||||
  #define MAX_NUM_SEGMENTS    18
 | 
			
		||||
  /* How many color transitions can run at once */
 | 
			
		||||
  #define MAX_NUM_TRANSITIONS  8
 | 
			
		||||
  /* How much data bytes all segments combined may allocate */
 | 
			
		||||
  #define MAX_SEGMENT_DATA  2048
 | 
			
		||||
  #define MAX_SEGMENT_DATA  4096
 | 
			
		||||
#else
 | 
			
		||||
#ifndef MAX_NUM_SEGMENTS
 | 
			
		||||
  #define MAX_NUM_SEGMENTS    16
 | 
			
		||||
#endif
 | 
			
		||||
  #define MAX_NUM_TRANSITIONS 16
 | 
			
		||||
  #define MAX_SEGMENT_DATA  8192
 | 
			
		||||
  #ifndef MAX_NUM_SEGMENTS
 | 
			
		||||
    #define MAX_NUM_SEGMENTS  32
 | 
			
		||||
  #endif
 | 
			
		||||
  #define MAX_NUM_TRANSITIONS 24
 | 
			
		||||
  #define MAX_SEGMENT_DATA  20480
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define LED_SKIP_AMOUNT  1
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +243,7 @@ class WS2812FX {
 | 
			
		|||
  
 | 
			
		||||
  // segment parameters
 | 
			
		||||
  public:
 | 
			
		||||
    typedef struct Segment { // 25 (28 in memory?) bytes
 | 
			
		||||
    typedef struct Segment { // 29 (32 in memory?) bytes
 | 
			
		||||
      uint16_t start;
 | 
			
		||||
      uint16_t stop; //segment invalid if stop == 0
 | 
			
		||||
      uint16_t offset;
 | 
			
		||||
| 
						 | 
				
			
			@ -257,6 +255,7 @@ class WS2812FX {
 | 
			
		|||
      uint8_t grouping, spacing;
 | 
			
		||||
      uint8_t opacity;
 | 
			
		||||
      uint32_t colors[NUM_COLORS];
 | 
			
		||||
      char *name;
 | 
			
		||||
      bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
 | 
			
		||||
        if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;
 | 
			
		||||
        if (c == colors[slot]) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -296,19 +295,19 @@ class WS2812FX {
 | 
			
		|||
      {
 | 
			
		||||
        return ((options >> n) & 0x01);
 | 
			
		||||
      }
 | 
			
		||||
      bool isSelected()
 | 
			
		||||
      inline bool isSelected()
 | 
			
		||||
      {
 | 
			
		||||
        return getOption(0);
 | 
			
		||||
      }
 | 
			
		||||
      bool isActive()
 | 
			
		||||
      inline bool isActive()
 | 
			
		||||
      {
 | 
			
		||||
        return stop > start;
 | 
			
		||||
      }
 | 
			
		||||
      uint16_t length()
 | 
			
		||||
      inline uint16_t length()
 | 
			
		||||
      {
 | 
			
		||||
        return stop - start;
 | 
			
		||||
      }
 | 
			
		||||
      uint16_t groupLength()
 | 
			
		||||
      inline uint16_t groupLength()
 | 
			
		||||
      {
 | 
			
		||||
        return grouping + spacing;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -345,17 +344,23 @@ class WS2812FX {
 | 
			
		|||
 | 
			
		||||
  // segment runtime parameters
 | 
			
		||||
    typedef struct Segment_runtime { // 28 bytes
 | 
			
		||||
      unsigned long next_time;
 | 
			
		||||
      uint32_t step;
 | 
			
		||||
      uint32_t call;
 | 
			
		||||
      uint16_t aux0;
 | 
			
		||||
      uint16_t aux1;
 | 
			
		||||
      unsigned long next_time;  // millis() of next update
 | 
			
		||||
      uint32_t step;  // custom "step" var
 | 
			
		||||
      uint32_t call;  // call counter
 | 
			
		||||
      uint16_t aux0;  // custom var
 | 
			
		||||
      uint16_t aux1;  // custom var
 | 
			
		||||
      byte* data = nullptr;
 | 
			
		||||
      bool allocateData(uint16_t len){
 | 
			
		||||
        if (data && _dataLen == len) return true; //already allocated
 | 
			
		||||
        deallocateData();
 | 
			
		||||
        if (WS2812FX::instance->_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
 | 
			
		||||
        data = new (std::nothrow) byte[len];
 | 
			
		||||
        // if possible use SPI RAM on ESP32
 | 
			
		||||
        #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
 | 
			
		||||
        if (psramFound())
 | 
			
		||||
          data = (byte*) ps_malloc(len);
 | 
			
		||||
        else
 | 
			
		||||
        #endif
 | 
			
		||||
          data = (byte*) malloc(len);
 | 
			
		||||
        if (!data) return false; //allocation failed
 | 
			
		||||
        WS2812FX::instance->_usedSegmentData += len;
 | 
			
		||||
        _dataLen = len;
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +368,7 @@ class WS2812FX {
 | 
			
		|||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
      void deallocateData(){
 | 
			
		||||
        delete[] data;
 | 
			
		||||
        free(data);
 | 
			
		||||
        data = nullptr;
 | 
			
		||||
        WS2812FX::instance->_usedSegmentData -= _dataLen;
 | 
			
		||||
        _dataLen = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -389,7 +394,7 @@ class WS2812FX {
 | 
			
		|||
       * the internal segment state should be reset. 
 | 
			
		||||
       * Call resetIfRequired before calling the next effect function.
 | 
			
		||||
       */
 | 
			
		||||
      void reset() { _requiresReset = true; }
 | 
			
		||||
      inline void reset() { _requiresReset = true; }
 | 
			
		||||
      private:
 | 
			
		||||
        uint16_t _dataLen = 0;
 | 
			
		||||
        bool _requiresReset = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -622,11 +627,12 @@ class WS2812FX {
 | 
			
		|||
      trigger(void),
 | 
			
		||||
      setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0),
 | 
			
		||||
      resetSegments(),
 | 
			
		||||
      populateDefaultSegments(),
 | 
			
		||||
      setPixelColor(uint16_t n, uint32_t c),
 | 
			
		||||
      setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
 | 
			
		||||
      show(void),
 | 
			
		||||
      setColorOrder(uint8_t co),
 | 
			
		||||
      setPixelSegment(uint8_t n);
 | 
			
		||||
      setPixelSegment(uint8_t n),
 | 
			
		||||
      deserializeMap(uint8_t n=0);
 | 
			
		||||
 | 
			
		||||
    bool
 | 
			
		||||
      isRgbw = false,
 | 
			
		||||
| 
						 | 
				
			
			@ -644,8 +650,6 @@ class WS2812FX {
 | 
			
		|||
      paletteFade = 0,
 | 
			
		||||
      paletteBlend = 0,
 | 
			
		||||
      milliampsPerLed = 55,
 | 
			
		||||
//      getStripType(uint8_t strip=0),
 | 
			
		||||
//      setStripType(uint8_t type, uint8_t strip=0),
 | 
			
		||||
      getBrightness(void),
 | 
			
		||||
      getMode(void),
 | 
			
		||||
      getSpeed(void),
 | 
			
		||||
| 
						 | 
				
			
			@ -654,24 +658,17 @@ class WS2812FX {
 | 
			
		|||
      getMaxSegments(void),
 | 
			
		||||
      //getFirstSelectedSegment(void),
 | 
			
		||||
      getMainSegmentId(void),
 | 
			
		||||
      getColorOrder(void),
 | 
			
		||||
      gamma8(uint8_t),
 | 
			
		||||
      gamma8_cal(uint8_t, float),
 | 
			
		||||
      sin_gap(uint16_t),
 | 
			
		||||
      get_random_wheel_index(uint8_t);
 | 
			
		||||
 | 
			
		||||
    int8_t
 | 
			
		||||
//      setStripPin(uint8_t strip, int8_t pin),
 | 
			
		||||
//      getStripPin(uint8_t strip=0),
 | 
			
		||||
//      setStripPinClk(uint8_t strip, int8_t pin),
 | 
			
		||||
//      getStripPinClk(uint8_t strip=0),
 | 
			
		||||
      tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec);
 | 
			
		||||
 | 
			
		||||
    uint16_t
 | 
			
		||||
      ablMilliampsMax,
 | 
			
		||||
      currentMilliamps,
 | 
			
		||||
//      setStripLen(uint8_t strip, uint16_t len),
 | 
			
		||||
//      getStripLen(uint8_t strip=0),
 | 
			
		||||
      triwave16(uint16_t),
 | 
			
		||||
      getFps();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -849,7 +846,6 @@ class WS2812FX {
 | 
			
		|||
      color_wipe(bool, bool),
 | 
			
		||||
      dynamic(bool),
 | 
			
		||||
      scan(bool),
 | 
			
		||||
      theater_chase(uint32_t, uint32_t, bool),
 | 
			
		||||
      running_base(bool,bool),
 | 
			
		||||
      larson_scanner(bool),
 | 
			
		||||
      sinelon_base(bool,bool),
 | 
			
		||||
| 
						 | 
				
			
			@ -857,8 +853,8 @@ class WS2812FX {
 | 
			
		|||
      chase(uint32_t, uint32_t, uint32_t, bool),
 | 
			
		||||
      gradient_base(bool),
 | 
			
		||||
      ripple_base(bool),
 | 
			
		||||
      police_base(uint32_t, uint32_t, bool),
 | 
			
		||||
      running(uint32_t, uint32_t),
 | 
			
		||||
      police_base(uint32_t, uint32_t, uint16_t),
 | 
			
		||||
      running(uint32_t, uint32_t, bool theatre=false),
 | 
			
		||||
      tricolor_chase(uint32_t, uint32_t),
 | 
			
		||||
      twinklefox_base(bool),
 | 
			
		||||
      spots_base(uint16_t),
 | 
			
		||||
| 
						 | 
				
			
			@ -869,8 +865,7 @@ class WS2812FX {
 | 
			
		|||
 | 
			
		||||
    void
 | 
			
		||||
      blendPixelColor(uint16_t n, uint32_t color, uint8_t blend),
 | 
			
		||||
      startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot),
 | 
			
		||||
      deserializeMap(void);
 | 
			
		||||
      startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot);
 | 
			
		||||
 | 
			
		||||
    uint16_t* customMappingTable = nullptr;
 | 
			
		||||
    uint16_t  customMappingSize  = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@
 | 
			
		|||
 | 
			
		||||
  Modified heavily for WLED
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "wled.h"
 | 
			
		||||
#include "FX.h"
 | 
			
		||||
#include "palettes.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@
 | 
			
		|||
  another example. Switches direction every 5 LEDs.
 | 
			
		||||
  {"map":[
 | 
			
		||||
  0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
 | 
			
		||||
  19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]
 | 
			
		||||
  19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//factory defaults LED setup
 | 
			
		||||
| 
						 | 
				
			
			@ -197,14 +197,13 @@ uint16_t WS2812FX::realPixelIndex(uint16_t i) {
 | 
			
		|||
  int16_t realIndex = iGroup;
 | 
			
		||||
  if (IS_REVERSE) {
 | 
			
		||||
    if (IS_MIRROR) {
 | 
			
		||||
      realIndex = (SEGMENT.length() -1) / 2 - iGroup;  //only need to index half the pixels
 | 
			
		||||
      realIndex = (SEGMENT.length() - 1) / 2 - iGroup;  //only need to index half the pixels
 | 
			
		||||
    } else {
 | 
			
		||||
      realIndex = SEGMENT.length() - iGroup - 1;
 | 
			
		||||
      realIndex = (SEGMENT.length() - 1) - iGroup;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  realIndex += SEGMENT.start;
 | 
			
		||||
 | 
			
		||||
  return realIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +224,6 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
 | 
			
		|||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (SEGLEN) {//from segment
 | 
			
		||||
 | 
			
		||||
    //color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
 | 
			
		||||
    if (_bri_t < 255) {  
 | 
			
		||||
      r = scale8(r, _bri_t);
 | 
			
		||||
| 
						 | 
				
			
			@ -235,12 +233,12 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
 | 
			
		|||
    }
 | 
			
		||||
    uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
 | 
			
		||||
 | 
			
		||||
    bool reversed = IS_REVERSE;
 | 
			
		||||
    /* Set all the pixels in the group */
 | 
			
		||||
    uint16_t realIndex = realPixelIndex(i);
 | 
			
		||||
    uint16_t len = SEGMENT.length();
 | 
			
		||||
 | 
			
		||||
    for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
 | 
			
		||||
      int indexSet = realIndex + (reversed ? -j : j);
 | 
			
		||||
      uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j);
 | 
			
		||||
      if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) {
 | 
			
		||||
        if (IS_MIRROR) { //set the corresponding mirrored pixel
 | 
			
		||||
          uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -252,8 +250,8 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
 | 
			
		|||
          busses.setPixelColor(indexMir, col);
 | 
			
		||||
        }
 | 
			
		||||
        /* offset/phase */
 | 
			
		||||
          indexSet += SEGMENT.offset;
 | 
			
		||||
          if (indexSet >= SEGMENT.stop) indexSet -= len;
 | 
			
		||||
        indexSet += SEGMENT.offset;
 | 
			
		||||
        if (indexSet >= SEGMENT.stop) indexSet -= len;
 | 
			
		||||
 | 
			
		||||
        if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
 | 
			
		||||
        busses.setPixelColor(indexSet, col);
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +259,6 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
 | 
			
		|||
    }
 | 
			
		||||
  } else { //live data, etc.
 | 
			
		||||
    if (i < customMappingSize) i = customMappingTable[i];
 | 
			
		||||
    
 | 
			
		||||
    uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
 | 
			
		||||
    busses.setPixelColor(i, col);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -542,6 +539,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
 | 
			
		|||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (i < customMappingSize) i = customMappingTable[i];
 | 
			
		||||
  if (i >= _length) return 0;
 | 
			
		||||
  
 | 
			
		||||
  return busses.getPixelColor(i);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -563,14 +561,14 @@ uint32_t WS2812FX::getLastShow(void) {
 | 
			
		|||
  return _lastShow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO these need to be on a per-strip basis
 | 
			
		||||
uint8_t WS2812FX::getColorOrder(void) {
 | 
			
		||||
  return COL_ORDER_GRB;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WS2812FX::setColorOrder(uint8_t co) {
 | 
			
		||||
  //bus->SetColorOrder(co);
 | 
			
		||||
}
 | 
			
		||||
// there is no longer any need for these two
 | 
			
		||||
//uint8_t WS2812FX::getColorOrder(void) {
 | 
			
		||||
//  return COL_ORDER_GRB;
 | 
			
		||||
//}
 | 
			
		||||
//
 | 
			
		||||
//void WS2812FX::setColorOrder(uint8_t co) {
 | 
			
		||||
//  //bus->SetColorOrder(co);
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
 | 
			
		||||
  if (n >= MAX_NUM_SEGMENTS) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -607,6 +605,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void WS2812FX::resetSegments() {
 | 
			
		||||
  for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete _segments[i].name;
 | 
			
		||||
  mainSegment = 0;
 | 
			
		||||
  memset(_segments, 0, sizeof(_segments));
 | 
			
		||||
  //memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
 | 
			
		||||
| 
						 | 
				
			
			@ -635,6 +634,25 @@ void WS2812FX::resetSegments() {
 | 
			
		|||
  _segment_runtimes[0].reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WS2812FX::populateDefaultSegments() {
 | 
			
		||||
  uint16_t length = 0;
 | 
			
		||||
  for (uint8_t i=0; i<busses.getNumBusses(); i++) {
 | 
			
		||||
    Bus *bus = busses.getBus(i);
 | 
			
		||||
    if (bus == nullptr) continue;
 | 
			
		||||
    _segments[i].start = bus->getStart();
 | 
			
		||||
    length += bus->getLength();
 | 
			
		||||
    _segments[i].stop = _segments[i].start + bus->getLength();
 | 
			
		||||
    _segments[i].mode = DEFAULT_MODE;
 | 
			
		||||
    _segments[i].colors[0] = DEFAULT_COLOR;
 | 
			
		||||
    _segments[i].speed = DEFAULT_SPEED;
 | 
			
		||||
    _segments[i].intensity = DEFAULT_INTENSITY;
 | 
			
		||||
    _segments[i].grouping = 1;
 | 
			
		||||
    _segments[i].setOption(SEG_OPTION_SELECTED, 1);
 | 
			
		||||
    _segments[i].setOption(SEG_OPTION_ON, 1);
 | 
			
		||||
    _segments[i].opacity = 255;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
 | 
			
		||||
void WS2812FX::setPixelSegment(uint8_t n)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1012,18 +1030,33 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
//load custom mapping table from JSON file
 | 
			
		||||
void WS2812FX::deserializeMap(void) {
 | 
			
		||||
  if (!WLED_FS.exists("/ledmap.json")) return;
 | 
			
		||||
void WS2812FX::deserializeMap(uint8_t n) {
 | 
			
		||||
  String fileName = String(F("/ledmap"));
 | 
			
		||||
  if (n) fileName += String(n);
 | 
			
		||||
  fileName += String(F(".json"));
 | 
			
		||||
  bool isFile = WLED_FS.exists(fileName);
 | 
			
		||||
 | 
			
		||||
  if (!isFile) {
 | 
			
		||||
    // erase custom mapping if selecting nonexistent ledmap.json (n==0)
 | 
			
		||||
    if (!n && customMappingTable != nullptr) {
 | 
			
		||||
      customMappingSize = 0;
 | 
			
		||||
      delete[] customMappingTable;
 | 
			
		||||
      customMappingTable = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DynamicJsonDocument doc(JSON_BUFFER_SIZE);  // full sized buffer for larger maps
 | 
			
		||||
  DEBUG_PRINT(F("Reading LED map from "));
 | 
			
		||||
  DEBUG_PRINTLN(fileName);
 | 
			
		||||
 | 
			
		||||
  DEBUG_PRINTLN(F("Reading LED map from /ledmap.json..."));
 | 
			
		||||
 | 
			
		||||
  if (!readObjectFromFile("/ledmap.json", nullptr, &doc)) return; //if file does not exist just exit
 | 
			
		||||
  if (!readObjectFromFile(fileName.c_str(), nullptr, &doc)) return; //if file does not exist just exit
 | 
			
		||||
 | 
			
		||||
  // erase old custom ledmap
 | 
			
		||||
  if (customMappingTable != nullptr) {
 | 
			
		||||
    customMappingSize = 0;
 | 
			
		||||
    delete[] customMappingTable;
 | 
			
		||||
    customMappingTable = nullptr;
 | 
			
		||||
    customMappingSize = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  JsonArray map = doc[F("map")];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -579,10 +579,11 @@ function populateSegments(s)
 | 
			
		|||
				<span class="checkmark schk"></span>
 | 
			
		||||
			</label>
 | 
			
		||||
			<div class="segname" onclick="selSegEx(${i})">
 | 
			
		||||
				Segment ${i}
 | 
			
		||||
				${inst.n ? inst.n : "Segment "+i}
 | 
			
		||||
			</div>
 | 
			
		||||
			<i class="icons e-icon flr ${expanded[i] ? "exp":""}" id="sege${i}" onclick="expand(${i})"></i>
 | 
			
		||||
			<div class="segin ${expanded[i] ? "expanded":""}" id="seg${i}">
 | 
			
		||||
				<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
 | 
			
		||||
				<div class="sbs">
 | 
			
		||||
				<i class="icons e-icon pwr ${powered[i] ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})"></i>
 | 
			
		||||
				<div class="sliderwrap il sws">
 | 
			
		||||
| 
						 | 
				
			
			@ -1498,10 +1499,11 @@ function selSeg(s){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function setSeg(s){
 | 
			
		||||
	var name  = d.getElementById(`seg${s}t`).value;
 | 
			
		||||
	var start = parseInt(d.getElementById(`seg${s}s`).value);
 | 
			
		||||
	var stop	= parseInt(d.getElementById(`seg${s}e`).value);
 | 
			
		||||
	if (stop <= start) {delSeg(s); return;}
 | 
			
		||||
	var obj = {"seg": {"id": s, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
 | 
			
		||||
	var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
 | 
			
		||||
	if (d.getElementById(`seg${s}grp`))
 | 
			
		||||
	{
 | 
			
		||||
		var grp = parseInt(d.getElementById(`seg${s}grp`).value);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1572
									
								
								wled00/html_ui.h
								
								
								
								
							
							
						
						
									
										1572
									
								
								wled00/html_ui.h
								
								
								
								
							
										
											
												Plik diff jest za duży
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -18,6 +18,29 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
 | 
			
		|||
  uint16_t start = elem[F("start")] | seg.start;
 | 
			
		||||
  int stop = elem["stop"] | -1;
 | 
			
		||||
 | 
			
		||||
    if (elem["n"]) {
 | 
			
		||||
      // name field exists
 | 
			
		||||
      String name = elem["n"];
 | 
			
		||||
      if (name.length()) {
 | 
			
		||||
        if (seg.name) delete seg.name;
 | 
			
		||||
        seg.name = new char[name.length()+1];
 | 
			
		||||
        strcpy(seg.name, name.c_str());
 | 
			
		||||
      } else {
 | 
			
		||||
        // but is empty
 | 
			
		||||
        elem.remove("n");
 | 
			
		||||
        if (seg.name) {
 | 
			
		||||
          delete seg.name;
 | 
			
		||||
          seg.name = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else if (elem[F("start")] || elem["stop"]) {
 | 
			
		||||
      // clearing or setting segment without name field
 | 
			
		||||
      if (seg.name) {
 | 
			
		||||
        delete seg.name;
 | 
			
		||||
        seg.name = nullptr;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (stop < 0) {
 | 
			
		||||
    uint16_t len = elem[F("len")];
 | 
			
		||||
    stop = (len > 0) ? start + len : seg.stop;
 | 
			
		||||
| 
						 | 
				
			
			@ -339,6 +362,8 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
 | 
			
		|||
  byte segbri = seg.opacity;
 | 
			
		||||
  root["bri"] = (segbri) ? segbri : 255;
 | 
			
		||||
 | 
			
		||||
  if (seg.name != nullptr) root["n"] = String(seg.name);
 | 
			
		||||
 | 
			
		||||
  char colstr[70]; colstr[0] = '['; colstr[1] = '\0'; //max len 68 (5 chan, all 255)
 | 
			
		||||
 | 
			
		||||
	for (uint8_t i = 0; i < 3; i++)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue