Merge branch 'fx-blending'
This commit is contained in:
commit
ddbe883d47
280
wled00/FX.cpp
280
wled00/FX.cpp
@ -604,11 +604,6 @@ static const char _data_FX_MODE_TWINKLE[] PROGMEM = "Twinkle@!,!;!,!;!;;m12=0";
|
||||
* Dissolve function
|
||||
*/
|
||||
uint16_t dissolve(uint32_t color) {
|
||||
//bool wa = (SEGCOLOR(1) != 0 && strip.getBrightness() < 255); //workaround, can't compare getPixel to color if not full brightness
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(SEGCOLOR(1));
|
||||
}
|
||||
|
||||
for (int j = 0; j <= SEGLEN / 15; j++) {
|
||||
if (random8() <= SEGMENT.intensity) {
|
||||
for (size_t times = 0; times < 10; times++) //attempt to spawn a new pixel 10 times
|
||||
@ -764,7 +759,7 @@ uint16_t mode_android(void) {
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1));
|
||||
}
|
||||
|
||||
if (SEGENV.aux1 > ((float)SEGMENT.intensity/255.0)*(float)SEGLEN)
|
||||
if (SEGENV.aux1 > (SEGMENT.intensity*SEGLEN)/255)
|
||||
{
|
||||
SEGENV.aux0 = 1;
|
||||
} else
|
||||
@ -814,7 +809,7 @@ static const char _data_FX_MODE_ANDROID[] PROGMEM = "Android@!,Width;!,!;!;;m12=
|
||||
*/
|
||||
uint16_t chase(uint32_t color1, uint32_t color2, uint32_t color3, bool do_palette) {
|
||||
uint16_t counter = strip.now * ((SEGMENT.speed >> 2) + 1);
|
||||
uint16_t a = counter * SEGLEN >> 16;
|
||||
uint16_t a = (counter * SEGLEN) >> 16;
|
||||
|
||||
bool chase_random = (SEGMENT.mode == FX_MODE_CHASE_RANDOM);
|
||||
if (chase_random) {
|
||||
@ -828,7 +823,7 @@ uint16_t chase(uint32_t color1, uint32_t color2, uint32_t color3, bool do_palett
|
||||
SEGENV.step = a;
|
||||
|
||||
// Use intensity setting to vary chase up to 1/2 string length
|
||||
uint8_t size = 1 + (SEGMENT.intensity * SEGLEN >> 10);
|
||||
uint8_t size = 1 + ((SEGMENT.intensity * SEGLEN) >> 10);
|
||||
|
||||
uint16_t b = a + size; //"trail" of chase, filled with color1
|
||||
if (b > SEGLEN) b -= SEGLEN;
|
||||
@ -1116,8 +1111,9 @@ static const char _data_FX_MODE_RUNNING_RANDOM[] PROGMEM = "Stream@!,Zone size;;
|
||||
|
||||
|
||||
uint16_t larson_scanner(bool dual) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t counter = strip.now * ((SEGMENT.speed >> 2) +8);
|
||||
uint16_t index = counter * SEGLEN >> 16;
|
||||
uint16_t index = (counter * SEGLEN) >> 16;
|
||||
|
||||
SEGMENT.fade_out(SEGMENT.intensity);
|
||||
|
||||
@ -1204,7 +1200,6 @@ uint16_t mode_fireworks() {
|
||||
const uint16_t height = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(SEGCOLOR(1));
|
||||
SEGENV.aux0 = UINT16_MAX;
|
||||
SEGENV.aux1 = UINT16_MAX;
|
||||
}
|
||||
@ -1305,24 +1300,23 @@ static const char _data_FX_MODE_FIRE_FLICKER[] PROGMEM = "Fire Flicker@!,!;!;!;0
|
||||
* Gradient run base function
|
||||
*/
|
||||
uint16_t gradient_base(bool loading) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t counter = strip.now * ((SEGMENT.speed >> 2) + 1);
|
||||
uint16_t pp = counter * SEGLEN >> 16;
|
||||
uint16_t pp = (counter * SEGLEN) >> 16;
|
||||
if (SEGENV.call == 0) pp = 0;
|
||||
float val; //0.0 = sec 1.0 = pri
|
||||
float brd = loading ? SEGMENT.intensity : SEGMENT.intensity/2;
|
||||
if (brd <1.0) brd = 1.0;
|
||||
int val; //0 = sec 1 = pri
|
||||
int brd = 1 + loading ? SEGMENT.intensity/2 : SEGMENT.intensity/4;
|
||||
//if (brd < 1) brd = 1;
|
||||
int p1 = pp-SEGLEN;
|
||||
int p2 = pp+SEGLEN;
|
||||
|
||||
for (int i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
if (loading)
|
||||
{
|
||||
val = abs(((i>pp) ? p2:pp) -i);
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
if (loading) {
|
||||
val = abs(((i>pp) ? p2:pp) - i);
|
||||
} else {
|
||||
val = MIN(abs(pp-i),MIN(abs(p1-i),abs(p2-i)));
|
||||
val = min(abs(pp-i),min(abs(p1-i),abs(p2-i)));
|
||||
}
|
||||
val = (brd > val) ? val/brd * 255 : 255;
|
||||
val = (brd > val) ? (val * 255) / brd : 255;
|
||||
SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(0), SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1), val));
|
||||
}
|
||||
|
||||
@ -1903,12 +1897,8 @@ static const char _data_FX_MODE_PRIDE_2015[] PROGMEM = "Pride 2015@!;;";
|
||||
//eight colored dots, weaving in and out of sync with each other
|
||||
uint16_t mode_juggle(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(192 - (3*SEGMENT.intensity/4));
|
||||
|
||||
CRGB fastled_col;
|
||||
byte dothue = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@ -2073,12 +2063,9 @@ static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!";
|
||||
|
||||
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
|
||||
uint16_t mode_bpm() {
|
||||
//CRGB fastled_col;
|
||||
uint32_t stp = (strip.now / 20) & 0xFF;
|
||||
uint8_t beat = beatsin8(SEGMENT.speed, 64, 255);
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
//fastled_col = ColorFromPalette(SEGPALETTE, stp + (i * 2), beat - stp + (i * 10));
|
||||
//SEGMENT.setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue);
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(stp + (i * 2), false, PALETTE_SOLID_WRAP, 0, beat - stp + (i * 10)));
|
||||
}
|
||||
|
||||
@ -2475,12 +2462,6 @@ static const char _data_FX_MODE_RIPPLE_RAINBOW[] PROGMEM = "Ripple Rainbow@!,Wav
|
||||
//
|
||||
// TwinkleFOX: Twinkling 'holiday' lights that fade in and out.
|
||||
// Colors are chosen from a palette. Read more about this effect using the link above!
|
||||
|
||||
// If COOL_LIKE_INCANDESCENT is set to 1, colors will
|
||||
// fade out slighted 'reddened', similar to how
|
||||
// incandescent bulbs change color as they get dim down.
|
||||
#define COOL_LIKE_INCANDESCENT 1
|
||||
|
||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat)
|
||||
{
|
||||
// Overall twinkle speed (changed)
|
||||
@ -2519,7 +2500,7 @@ CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat)
|
||||
CRGB c;
|
||||
if (bright > 0) {
|
||||
c = ColorFromPalette(SEGPALETTE, hue, bright, NOBLEND);
|
||||
if(COOL_LIKE_INCANDESCENT == 1) {
|
||||
if (!SEGMENT.check1) {
|
||||
// This code takes a pixel, and if its in the 'fading down'
|
||||
// part of the cycle, it adjusts the color a little bit like the
|
||||
// way that incandescent bulbs fade toward 'red' as they dim.
|
||||
@ -2605,14 +2586,14 @@ uint16_t mode_twinklefox()
|
||||
{
|
||||
return twinklefox_base(false);
|
||||
}
|
||||
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate;;!";
|
||||
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate,,,,Cool;;!";
|
||||
|
||||
|
||||
uint16_t mode_twinklecat()
|
||||
{
|
||||
return twinklefox_base(true);
|
||||
}
|
||||
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate;;!";
|
||||
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate,,,,Cool;;!";
|
||||
|
||||
|
||||
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
||||
@ -2930,7 +2911,7 @@ uint16_t mode_glitter()
|
||||
static const char _data_FX_MODE_GLITTER[] PROGMEM = "Glitter@!,!,,,,,Overlay;1,2,Glitter color;!;;pal=0,m12=0"; //pixels
|
||||
|
||||
|
||||
//Solid colour background with glitter
|
||||
//Solid colour background with glitter (can be replaced by Glitter)
|
||||
uint16_t mode_solid_glitter()
|
||||
{
|
||||
SEGMENT.fill(SEGCOLOR(0));
|
||||
@ -3020,8 +3001,7 @@ static const char _data_FX_MODE_POPCORN[] PROGMEM = "Popcorn@!,!,,,,,Overlay;!,!
|
||||
|
||||
uint16_t candle(bool multi)
|
||||
{
|
||||
if (multi)
|
||||
{
|
||||
if (multi && SEGLEN > 1) {
|
||||
//allocate segment data
|
||||
uint16_t dataSize = max(1, SEGLEN -1) *3; //max. 1365 pixels (ESP8266)
|
||||
if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed
|
||||
@ -3590,8 +3570,8 @@ uint16_t mode_percent(void) {
|
||||
|
||||
uint8_t percent = SEGMENT.intensity;
|
||||
percent = constrain(percent, 0, 200);
|
||||
uint16_t active_leds = (percent < 100) ? SEGLEN * percent / 100.0
|
||||
: SEGLEN * (200 - percent) / 100.0;
|
||||
uint16_t active_leds = (percent < 100) ? roundf(SEGLEN * percent / 100.0f)
|
||||
: roundf(SEGLEN * (200 - percent) / 100.0f);
|
||||
|
||||
uint8_t size = (1 + ((SEGMENT.speed * SEGLEN) >> 11));
|
||||
if (SEGMENT.speed == 255) size = 255;
|
||||
@ -4582,11 +4562,6 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
uint16_t x, y;
|
||||
|
||||
// initialize on first call
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
|
||||
unsigned long t = millis()/128; // timebase
|
||||
// outer stars
|
||||
@ -4621,7 +4596,6 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
SEGENV.aux0 = 0; // start with red hue
|
||||
}
|
||||
|
||||
@ -4673,12 +4647,7 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
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));
|
||||
@ -4744,12 +4713,7 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(128);
|
||||
|
||||
const uint16_t maxDim = MAX(cols, rows)/2;
|
||||
unsigned long t = millis() / (32 - (SEGMENT.speed>>3));
|
||||
unsigned long t_20 = t/20; // softhack007: pre-calculating this gives about 10% speedup
|
||||
@ -4809,10 +4773,6 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(16);
|
||||
for (size_t i = 8; i > 0; i--) {
|
||||
SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1),
|
||||
@ -5256,12 +5216,7 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(SEGMENT.custom1>>2);
|
||||
|
||||
uint_fast32_t t = (millis() * 8) / (256 - SEGMENT.speed); // optimized to avoid float
|
||||
for (int i = 0; i < cols; i++) {
|
||||
uint16_t thisVal = inoise8(i * 30, t, t);
|
||||
@ -5352,12 +5307,7 @@ uint16_t mode_2DPulser(void) { // By: ldirko https://edi
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(8 - (SEGMENT.intensity>>5));
|
||||
|
||||
uint32_t a = strip.now / (18 - SEGMENT.speed / 16);
|
||||
uint16_t x = (a / 14) % cols;
|
||||
uint16_t y = map((sin8(a * 5) + sin8(a * 4) + sin8(a * 2)), 0, 765, rows-1, 0);
|
||||
@ -5410,14 +5360,9 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
const uint8_t kBorderWidth = 2;
|
||||
|
||||
SEGMENT.fadeToBlackBy(24);
|
||||
|
||||
uint8_t blurAmount = SEGMENT.custom3>>1; // reduced resolution slider
|
||||
SEGMENT.blur(blurAmount);
|
||||
|
||||
@ -5538,10 +5483,6 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
uint32_t tb = strip.now >> 12; // every ~4s
|
||||
if (tb > SEGENV.step) {
|
||||
int8_t dir = ++SEGENV.aux0;
|
||||
@ -5607,7 +5548,6 @@ uint16_t mode_2Dcrazybees(void) {
|
||||
bee_t *bee = reinterpret_cast<bee_t*>(SEGENV.data);
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
bee[i].posX = random8(0, cols);
|
||||
bee[i].posY = random8(0, rows);
|
||||
@ -5616,7 +5556,7 @@ uint16_t mode_2Dcrazybees(void) {
|
||||
}
|
||||
|
||||
if (millis() > SEGENV.step) {
|
||||
SEGENV.step = millis() + (FRAMETIME * 8 / ((SEGMENT.speed>>5)+1));
|
||||
SEGENV.step = millis() + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1));
|
||||
|
||||
SEGMENT.fadeToBlackBy(32);
|
||||
|
||||
@ -5679,9 +5619,9 @@ uint16_t mode_2Dghostrider(void) {
|
||||
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
||||
SEGENV.aux0 = cols;
|
||||
SEGENV.aux1 = rows;
|
||||
SEGMENT.fill(BLACK);
|
||||
random16_set_seed(strip.now);
|
||||
lighter->angleSpeed = random8(0,20) - 10;
|
||||
lighter->gAngle = random16();
|
||||
lighter->Vspeed = 5;
|
||||
lighter->gPosX = (cols/2) * 10;
|
||||
lighter->gPosY = (rows/2) * 10;
|
||||
@ -5689,6 +5629,7 @@ uint16_t mode_2Dghostrider(void) {
|
||||
lighter->lightersPosX[i] = lighter->gPosX;
|
||||
lighter->lightersPosY[i] = lighter->gPosY + i;
|
||||
lighter->time[i] = i * 2;
|
||||
lighter->reg[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5763,7 +5704,7 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
|
||||
SEGENV.aux0 = cols; // re-initialise if virtual size changes
|
||||
SEGENV.aux1 = rows;
|
||||
SEGMENT.fill(BLACK);
|
||||
//SEGMENT.fill(BLACK);
|
||||
for (size_t i = 0; i < MAX_BLOBS; i++) {
|
||||
blob->r[i] = random8(1, cols>8 ? (cols/4) : 2);
|
||||
blob->sX[i] = (float) random8(3, cols) / (float)(256 - SEGMENT.speed); // speed x
|
||||
@ -5777,7 +5718,7 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
}
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(20);
|
||||
SEGMENT.fadeToBlackBy((SEGMENT.custom2>>3)+1);
|
||||
|
||||
// Bounce balls around
|
||||
for (size_t i = 0; i < Amount; i++) {
|
||||
@ -5833,7 +5774,7 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
return FRAMETIME;
|
||||
}
|
||||
#undef MAX_BLOBS
|
||||
static const char _data_FX_MODE_2DBLOBS[] PROGMEM = "Blobs@!,# blobs,Blur;!;!;2;c1=8";
|
||||
static const char _data_FX_MODE_2DBLOBS[] PROGMEM = "Blobs@!,# blobs,Blur,Trail;!;!;2;c1=8";
|
||||
|
||||
|
||||
////////////////////////////
|
||||
@ -5845,8 +5786,8 @@ uint16_t mode_2Dscrollingtext(void) {
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
int letterWidth;
|
||||
int letterHeight;
|
||||
int letterWidth, rotLW;
|
||||
int letterHeight, rotLH;
|
||||
switch (map(SEGMENT.custom2, 0, 255, 1, 5)) {
|
||||
default:
|
||||
case 1: letterWidth = 4; letterHeight = 6; break;
|
||||
@ -5855,59 +5796,84 @@ uint16_t mode_2Dscrollingtext(void) {
|
||||
case 4: letterWidth = 7; letterHeight = 9; break;
|
||||
case 5: letterWidth = 5; letterHeight = 12; break;
|
||||
}
|
||||
const bool zero = SEGMENT.check3;
|
||||
const int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-letterHeight)/2;
|
||||
// letters are rotated
|
||||
if (((SEGMENT.custom3+1)>>3) % 2) {
|
||||
rotLH = letterWidth;
|
||||
rotLW = letterHeight;
|
||||
} else {
|
||||
rotLW = letterWidth;
|
||||
rotLH = letterHeight;
|
||||
}
|
||||
|
||||
char text[WLED_MAX_SEGNAME_LEN+1] = {'\0'};
|
||||
if (SEGMENT.name) for (size_t i=0,j=0; i<strlen(SEGMENT.name); i++) if (SEGMENT.name[i]>31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i];
|
||||
const bool zero = strchr(text, '0') != nullptr;
|
||||
const int numberOfLetters = strlen(text);
|
||||
|
||||
if (!strlen(text)
|
||||
|| !strncmp_P(text,PSTR("#DATE"),5)
|
||||
|| !strncmp_P(text,PSTR("#DDMM"),5)
|
||||
|| !strncmp_P(text,PSTR("#MMDD"),5)
|
||||
|| !strncmp_P(text,PSTR("#TIME"),5)
|
||||
|| !strncmp_P(text,PSTR("#HHMM"),5)) { // fallback if empty segment name: display date and time
|
||||
char sec[5];
|
||||
byte AmPmHour = hour(localTime);
|
||||
boolean isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
}
|
||||
if (useAMPM) sprintf_P(sec, PSTR(" %2s"), (isitAM ? "AM" : "PM"));
|
||||
else sprintf_P(sec, PSTR(":%02d"), second(localTime));
|
||||
if (!strncmp_P(text,PSTR("#DATE"),5)) sprintf_P(text, zero?PSTR("%02d.%02d.%04d"):PSTR("%d.%d.%d"), day(localTime), month(localTime), year(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#DDMM"),5)) sprintf_P(text, zero?PSTR("%02d.%02d"):PSTR("%d.%d"), day(localTime), month(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d"):PSTR("%d/%d"), month(localTime), day(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s"):PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
||||
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d"):PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
||||
else sprintf_P(text, zero?PSTR("%s %02d, %04d %02d:%02d%s"):PSTR("%s %d, %d %d:%02d%s"), monthShortStr(month(localTime)), day(localTime), year(localTime), AmPmHour, minute(localTime), sec);
|
||||
char sec[5];
|
||||
int AmPmHour = hour(localTime);
|
||||
bool isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
sprintf_P(sec, PSTR(" %2s"), (isitAM ? "AM" : "PM"));
|
||||
} else {
|
||||
sprintf_P(sec, PSTR(":%02d"), second(localTime));
|
||||
}
|
||||
const int numberOfLetters = strlen(text);
|
||||
|
||||
if (SEGENV.step < millis()) {
|
||||
if ((numberOfLetters * letterWidth) > cols) ++SEGENV.aux0 %= (numberOfLetters * letterWidth) + cols; // offset
|
||||
else SEGENV.aux0 = (cols + (numberOfLetters * letterWidth))/2;
|
||||
if (!numberOfLetters) { // fallback if empty segment name: display date and time
|
||||
sprintf_P(text, PSTR("%s %d, %d %d:%02d%s"), monthShortStr(month(localTime)), day(localTime), year(localTime), AmPmHour, minute(localTime), sec);
|
||||
} else {
|
||||
if (!strncmp_P(text,PSTR("#DATE"),5)) sprintf_P(text, zero?PSTR("%02d.%02d.%04d"):PSTR("%d.%d.%d"), day(localTime), month(localTime), year(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#DDMM"),5)) sprintf_P(text, zero?PSTR("%02d.%02d") :PSTR("%d.%d"), day(localTime), month(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d") :PSTR("%d/%d"), month(localTime), day(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s") :PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
||||
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d") :PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
||||
}
|
||||
|
||||
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;
|
||||
if (SEGMENT.intensity == 255) {
|
||||
yoffset = (2 * frac * rows)/speed - rows;
|
||||
} else if (SEGMENT.intensity == 0) {
|
||||
yoffset = rows - (2 * frac * rows)/speed;
|
||||
}
|
||||
}
|
||||
|
||||
if (SEGENV.step < now) {
|
||||
// calculate start offset
|
||||
if (width > cols) {
|
||||
if (SEGMENT.check3) {
|
||||
if (SEGENV.aux0 == 0) SEGENV.aux0 = width + cols - 1;
|
||||
else --SEGENV.aux0;
|
||||
} else ++SEGENV.aux0 %= width + cols;
|
||||
} else SEGENV.aux0 = (cols + width)/2;
|
||||
++SEGENV.aux1 &= 0xFF; // color shift
|
||||
SEGENV.step = millis() + map(SEGMENT.speed, 0, 255, 10*FRAMETIME_FIXED, 2*FRAMETIME_FIXED);
|
||||
if (!SEGMENT.check2) {
|
||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++ )
|
||||
SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1));
|
||||
}
|
||||
SEGENV.step = 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
|
||||
|
||||
for (int i = 0; i < numberOfLetters; i++) {
|
||||
if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen
|
||||
int xoffset = int(cols) - int(SEGENV.aux0) + rotLW*i;
|
||||
if (xoffset + rotLW < 0) continue; // don't draw characters off-screen
|
||||
uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0);
|
||||
uint32_t col2 = BLACK;
|
||||
if (SEGMENT.check1 && SEGMENT.palette == 0) {
|
||||
col1 = SEGCOLOR(0);
|
||||
col2 = SEGCOLOR(2);
|
||||
}
|
||||
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2);
|
||||
SEGMENT.drawCharacter(text[i], xoffset, yoffset, letterWidth, letterHeight, col1, col2, (SEGMENT.custom3+1)>>3);
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,,Gradient,Overlay,0;!,!,Gradient;!;2;ix=128,c1=0,rev=0,mi=0,rY=0,mY=0";
|
||||
static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,Rotate,Gradient,Overlay,Reverse;!,!,Gradient;!;2;ix=128,c1=0,c3=0,rev=0,mi=0,rY=0,mY=0";
|
||||
|
||||
|
||||
////////////////////////////
|
||||
@ -5924,10 +5890,6 @@ uint16_t mode_2Ddriftrose(void) {
|
||||
const float CY = (rows-rows%2)/2.f - .5f;
|
||||
const float L = min(cols, rows) / 2.f;
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(32+(SEGMENT.speed>>3));
|
||||
for (size_t i = 1; i < 37; i++) {
|
||||
uint32_t x = (CX + (sin_t(radians(i * 10)) * (beatsin8(i, 0, L*2)-L))) * 255.f;
|
||||
@ -6100,8 +6062,6 @@ 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];
|
||||
|
||||
// printUmData();
|
||||
|
||||
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);
|
||||
@ -6124,10 +6084,6 @@ uint16_t mode_2DWaverly(void) {
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -6175,6 +6131,7 @@ typedef struct Gravity {
|
||||
// * GRAVCENTER //
|
||||
///////////////////////
|
||||
uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
const uint16_t dataSize = sizeof(gravity);
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
@ -6193,7 +6150,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 32, 0, (float)SEGLEN/2.0); // map to pixels available in current segment
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 32, 0, (float)SEGLEN/2.0f); // map to pixels available in current segment
|
||||
uint16_t tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||
|
||||
@ -6223,6 +6180,7 @@ static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall,
|
||||
// * GRAVCENTRIC //
|
||||
///////////////////////
|
||||
uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
uint16_t dataSize = sizeof(gravity);
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
@ -6241,10 +6199,10 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
|
||||
//SEGMENT.fade_out(240); // twice? really?
|
||||
SEGMENT.fade_out(253); // 50%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0;
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0); // map to pixels availeable in current segment
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment
|
||||
int tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||
|
||||
@ -6274,6 +6232,7 @@ static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fal
|
||||
// * GRAVIMETER //
|
||||
///////////////////////
|
||||
uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
uint16_t dataSize = sizeof(gravity);
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
@ -6320,6 +6279,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter@Rate of fall,
|
||||
// * JUGGLES //
|
||||
//////////////////////
|
||||
uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -6343,6 +6303,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!;
|
||||
// * MATRIPIX //
|
||||
//////////////////////
|
||||
uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||
|
||||
um_data_t *um_data;
|
||||
@ -6374,6 +6335,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix@!,Brightness;!,!;
|
||||
// * MIDNOISE //
|
||||
//////////////////////
|
||||
uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
// Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1.
|
||||
|
||||
um_data_t *um_data;
|
||||
@ -6477,6 +6439,7 @@ static const char _data_FX_MODE_NOISEMETER[] PROGMEM = "Noisemeter@Fade rate,Wid
|
||||
// * PIXELWAVE //
|
||||
//////////////////////
|
||||
uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
@ -6552,6 +6515,7 @@ static const char _data_FX_MODE_PLASMOID[] PROGMEM = "Plasmoid@Phase,# of pixels
|
||||
///////////////////////
|
||||
// Andrew's crappy peak detector. If I were 40+ years younger, I'd learn signal processing.
|
||||
uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
uint16_t size = 0;
|
||||
uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254);
|
||||
@ -6595,6 +6559,7 @@ static const char _data_FX_MODE_PUDDLEPEAK[] PROGMEM = "Puddlepeak@Fade rate,Pud
|
||||
// * PUDDLES //
|
||||
//////////////////////
|
||||
uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t size = 0;
|
||||
uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254);
|
||||
uint16_t pos = random16(SEGLEN); // Set a random starting position.
|
||||
@ -6626,6 +6591,7 @@ static const char _data_FX_MODE_PUDDLES[] PROGMEM = "Puddles@Fade rate,Puddle si
|
||||
// * PIXELS //
|
||||
//////////////////////
|
||||
uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed
|
||||
uint8_t *myVals = reinterpret_cast<uint8_t*>(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low.
|
||||
@ -6659,6 +6625,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels
|
||||
// ** Blurz //
|
||||
//////////////////////
|
||||
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
|
||||
|
||||
um_data_t *um_data;
|
||||
@ -6695,6 +6662,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color
|
||||
// ** DJLight //
|
||||
/////////////////////////
|
||||
uint16_t mode_DJLight(void) { // Written by ??? Adapted by Will Tatam.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const int mid = SEGLEN / 2;
|
||||
|
||||
um_data_t *um_data;
|
||||
@ -6728,6 +6696,7 @@ static const char _data_FX_MODE_DJLIGHT[] PROGMEM = "DJ Light@Speed;;;1f;m12=2,s
|
||||
// ** Freqmap //
|
||||
////////////////////
|
||||
uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. Would be better if a higher framerate.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
// Start frequency = 60 Hz and log10(60) = 1.78
|
||||
// End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10
|
||||
|
||||
@ -6764,6 +6733,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting
|
||||
// ** Freqmatrix //
|
||||
///////////////////////
|
||||
uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -6829,24 +6799,27 @@ uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||
}
|
||||
float FFT_MajorPeak = *(float*)um_data->u_data[4];
|
||||
float my_magnitude = *(float*)um_data->u_data[5] / 16.0f;
|
||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1.0f; // log10(0) is "forbidden" (throws exception)
|
||||
|
||||
uint16_t fadeRate = 2*SEGMENT.speed - SEGMENT.speed*SEGMENT.speed/255; // Get to 255 as quick as you can.
|
||||
// this code translates to speed * (2 - speed/255) which is a) speed*2 or b) speed (when speed is 255)
|
||||
// and since fade_out() can only take 0-255 it will behave incorrectly when speed > 127
|
||||
//uint16_t fadeRate = 2*SEGMENT.speed - SEGMENT.speed*SEGMENT.speed/255; // Get to 255 as quick as you can.
|
||||
uint16_t fadeRate = SEGMENT.speed*SEGMENT.speed; // Get to 255 as quick as you can.
|
||||
fadeRate = map(fadeRate, 0, 65535, 1, 255);
|
||||
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 64;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(fadeRate);
|
||||
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow
|
||||
for (int i=0; i < SEGMENT.intensity/32+1; i++) {
|
||||
uint16_t locn = random16(0,SEGLEN);
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude));
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_freqpixels()
|
||||
static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Starting color and # of pixels;;;1f;m12=0,si=0"; // Pixels, Beatsin
|
||||
static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Starting color and # of pixels;!,!,;!;1f;m12=0,si=0"; // Pixels, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -6865,6 +6838,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta
|
||||
// As a compromise between speed and accuracy we are currently sampling with 10240Hz, from which we can then determine with a 512bin FFT our max frequency is 5120Hz.
|
||||
// Depending on the music stream you have you might find it useful to change the frequency mapping.
|
||||
uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung.
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -6921,7 +6895,7 @@ static const char _data_FX_MODE_FREQWAVE[] PROGMEM = "Freqwave@Speed,Sound effec
|
||||
// ** Gravfreq //
|
||||
///////////////////////
|
||||
uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t dataSize = sizeof(gravity);
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||
@ -6938,9 +6912,9 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
SEGMENT.fade_out(250);
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0f, 0,32, 0, (float)SEGLEN/2.0); // map to pixels availeable in current segment
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0f, 0,32, 0, (float)SEGLEN/2.0f); // map to pixels availeable in current segment
|
||||
int tempsamp = constrain(mySampleAvg,0,SEGLEN/2); // Keep the sample from overflowing.
|
||||
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||
|
||||
@ -6973,6 +6947,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sens
|
||||
// ** Noisemove //
|
||||
//////////////////////
|
||||
uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -6980,8 +6955,6 @@ uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuli
|
||||
}
|
||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
//SEGMENT.fade_out(224); // Just in case something doesn't get faded.
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 96;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(4+ SEGMENT.speed/4);
|
||||
|
||||
@ -7001,6 +6974,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin
|
||||
// ** Rocktaves //
|
||||
//////////////////////
|
||||
uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
@ -7009,8 +6983,7 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac
|
||||
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
||||
float my_magnitude = *(float*) um_data->u_data[5] / 16.0f;
|
||||
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
SEGMENT.fadeToBlackBy(16); // Just in case something doesn't get faded.
|
||||
SEGMENT.fadeToBlackBy(16); // Just in case something doesn't get faded.
|
||||
|
||||
float frTemp = FFT_MajorPeak;
|
||||
uint8_t octCount = 0; // Octave counter.
|
||||
@ -7025,8 +6998,8 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac
|
||||
frTemp = frTemp/2;
|
||||
}
|
||||
|
||||
frTemp -=132; // This should give us a base musical note of C3
|
||||
frTemp = fabsf(frTemp * 2.1f); // Fudge factors to compress octave range starting at 0 and going to 255;
|
||||
frTemp -= 132.0f; // This should give us a base musical note of C3
|
||||
frTemp = fabsf(frTemp * 2.1f); // Fudge factors to compress octave range starting at 0 and going to 255;
|
||||
|
||||
uint16_t i = map(beatsin8(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1);
|
||||
i = constrain(i, 0, SEGLEN-1);
|
||||
@ -7042,7 +7015,7 @@ static const char _data_FX_MODE_ROCKTAVES[] PROGMEM = "Rocktaves@;!,!;!;1f;m12=1
|
||||
///////////////////////
|
||||
// Combines peak detection with FFT_MajorPeak and FFT_Magnitude.
|
||||
uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tuline
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
@ -7117,7 +7090,6 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
||||
rippleTime = true;
|
||||
}
|
||||
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 64;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(SEGMENT.speed);
|
||||
|
||||
|
79
wled00/FX.h
79
wled00/FX.h
@ -381,6 +381,26 @@ typedef struct Segment {
|
||||
byte *data; // effect data pointer
|
||||
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
||||
|
||||
typedef struct TemporarySegmentData {
|
||||
uint16_t _optionsT;
|
||||
uint32_t _colorT[NUM_COLORS];
|
||||
uint8_t _speedT;
|
||||
uint8_t _intensityT;
|
||||
uint8_t _custom1T, _custom2T; // custom FX parameters/sliders
|
||||
struct {
|
||||
uint8_t _custom3T : 5; // reduced range slider (0-31)
|
||||
bool _check1T : 1; // checkmark 1
|
||||
bool _check2T : 1; // checkmark 2
|
||||
bool _check3T : 1; // checkmark 3
|
||||
};
|
||||
uint16_t _aux0T;
|
||||
uint16_t _aux1T;
|
||||
uint32_t _stepT;
|
||||
uint32_t _callT;
|
||||
uint8_t *_dataT;
|
||||
uint16_t _dataLenT;
|
||||
} tmpsegd_t;
|
||||
|
||||
private:
|
||||
union {
|
||||
uint8_t _capabilities;
|
||||
@ -396,43 +416,33 @@ typedef struct Segment {
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
// perhaps this should be per segment, not static
|
||||
static CRGBPalette16 _randomPalette;
|
||||
static CRGBPalette16 _newRandomPalette;
|
||||
static unsigned long _lastPaletteChange;
|
||||
static CRGBPalette16 _randomPalette; // actual random palette
|
||||
static CRGBPalette16 _newRandomPalette; // target random palette
|
||||
static unsigned long _lastPaletteChange; // last random palette change time in millis()
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
static bool _modeBlend; // mode/effect blending semaphore
|
||||
#endif
|
||||
|
||||
// transition data, valid only if transitional==true, holds values during transition (72 bytes)
|
||||
struct Transition {
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
tmpsegd_t _segT; // previous segment environment
|
||||
uint8_t _modeT; // previous mode/effect
|
||||
#else
|
||||
uint32_t _colorT[NUM_COLORS];
|
||||
#endif
|
||||
uint8_t _briT; // temporary brightness
|
||||
uint8_t _cctT; // temporary CCT
|
||||
CRGBPalette16 _palT; // temporary palette
|
||||
uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 belnds possible)
|
||||
uint8_t _modeP; // previous mode/effect
|
||||
//uint16_t _aux0, _aux1; // previous mode/effect runtime data
|
||||
//uint32_t _step, _call; // previous mode/effect runtime data
|
||||
//byte *_data; // previous mode/effect runtime data
|
||||
unsigned long _start; // must accommodate millis()
|
||||
unsigned long _start; // must accommodate millis()
|
||||
uint16_t _dur;
|
||||
Transition(uint16_t dur=750)
|
||||
: _briT(255)
|
||||
, _cctT(127)
|
||||
, _palT(CRGBPalette16(CRGB::Black))
|
||||
: _palT(CRGBPalette16(CRGB::Black))
|
||||
, _prevPaletteBlends(0)
|
||||
, _modeP(FX_MODE_STATIC)
|
||||
, _start(millis())
|
||||
, _dur(dur)
|
||||
{}
|
||||
Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o)
|
||||
: _briT(b)
|
||||
, _cctT(c)
|
||||
, _palT(CRGBPalette16(CRGB::Black))
|
||||
, _prevPaletteBlends(0)
|
||||
, _modeP(FX_MODE_STATIC)
|
||||
, _start(millis())
|
||||
, _dur(d)
|
||||
{
|
||||
for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = o[i];
|
||||
}
|
||||
} *_t;
|
||||
|
||||
public:
|
||||
@ -471,6 +481,9 @@ typedef struct Segment {
|
||||
_t(nullptr)
|
||||
{
|
||||
//refreshLightCapabilities();
|
||||
#ifdef WLED_DEBUG
|
||||
//Serial.printf("-- Creating segment: %p\n", this);
|
||||
#endif
|
||||
}
|
||||
|
||||
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) {
|
||||
@ -482,14 +495,14 @@ typedef struct Segment {
|
||||
Segment(Segment &&orig) noexcept; // move constructor
|
||||
|
||||
~Segment() {
|
||||
//#ifdef WLED_DEBUG
|
||||
//Serial.print(F("Destroying segment:"));
|
||||
#ifdef WLED_DEBUG
|
||||
//Serial.printf("-- Destroying segment: %p\n", this);
|
||||
//if (name) Serial.printf(" %s (%p)", name, name);
|
||||
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
||||
//Serial.println();
|
||||
//#endif
|
||||
#endif
|
||||
if (name) { delete[] name; name = nullptr; }
|
||||
if (_t) { transitional = false; delete _t; _t = nullptr; }
|
||||
stopTransition();
|
||||
deallocateData();
|
||||
}
|
||||
|
||||
@ -515,6 +528,9 @@ typedef struct Segment {
|
||||
|
||||
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
|
||||
static void addUsedSegmentData(int len) { _usedSegmentData += len; }
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
static void modeBlend(bool blend) { _modeBlend = blend; }
|
||||
#endif
|
||||
static void handleRandomPalette();
|
||||
|
||||
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t segId = 255);
|
||||
@ -542,7 +558,12 @@ typedef struct Segment {
|
||||
|
||||
// transition functions
|
||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||
void stopTransition(void);
|
||||
void handleTransition(void);
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
void swapSegenv(tmpsegd_t &tmpSegD);
|
||||
void restoreSegenv(tmpsegd_t &tmpSegD);
|
||||
#endif
|
||||
uint16_t progress(void); //transition progression between 0-65535
|
||||
uint8_t currentBri(uint8_t briNew, bool useCct = false);
|
||||
uint8_t currentMode(uint8_t modeNew);
|
||||
@ -604,9 +625,9 @@ typedef struct Segment {
|
||||
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
|
||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0);
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, uint8_t rotate = 0);
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, uint8_t rotate = 0) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate); } // automatic inline
|
||||
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
|
||||
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
|
||||
void blur2d(fract8 blur_amount) { blur(blur_amount); }
|
||||
|
@ -216,23 +216,29 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
y *= groupLength(); // expand to physical pixels
|
||||
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
|
||||
|
||||
uint32_t tmpCol = col;
|
||||
for (int j = 0; j < grouping; j++) { // groupping vertically
|
||||
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
||||
uint16_t xX = (x+g), yY = (y+j);
|
||||
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
||||
|
||||
strip.setPixelColorXY(start + xX, startY + yY, col);
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
// if blending modes, blend with underlying pixel
|
||||
if (_modeBlend) tmpCol = color_blend(strip.getPixelColorXY(start + xX, startY + yY), col, 0xFFFFU - progress(), true);
|
||||
#endif
|
||||
|
||||
strip.setPixelColorXY(start + xX, startY + yY, tmpCol);
|
||||
|
||||
if (mirror) { //set the corresponding horizontally mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
|
||||
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
|
||||
}
|
||||
if (mirror_y) { //set the corresponding vertically mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, tmpCol);
|
||||
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, tmpCol);
|
||||
}
|
||||
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
|
||||
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col);
|
||||
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, tmpCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,7 +571,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
|
||||
// draws a raster font character on canvas
|
||||
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
|
||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, uint8_t rotate) {
|
||||
if (!isActive()) return; // not active
|
||||
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
||||
chr -= 32; // align with font table entries
|
||||
@ -578,9 +584,6 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
||||
|
||||
//if (w<5 || w>6 || h!=8) return;
|
||||
for (int i = 0; i<h; i++) { // character height
|
||||
int16_t y0 = y + i;
|
||||
if (y0 < 0) continue; // drawing off-screen
|
||||
if (y0 >= rows) break; // drawing off-screen
|
||||
uint8_t bits = 0;
|
||||
switch (font) {
|
||||
case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); break; // 5x8 font
|
||||
@ -592,8 +595,15 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
||||
}
|
||||
col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND);
|
||||
for (int j = 0; j<w; j++) { // character width
|
||||
int16_t x0 = x + (w-1) - j;
|
||||
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
|
||||
int x0, y0;
|
||||
switch (rotate) {
|
||||
case 3: x0 = x + (h-1) - i; y0 = y + (w-1) - j; break;
|
||||
case 2: x0 = x + j; y0 = y + (h-1) - i; break;
|
||||
case 1: x0 = x + i; y0 = y + j; break;
|
||||
default: x0 = x + (w-1) - j; y0 = y + i; break;
|
||||
}
|
||||
if (x0 < 0 || x0 >= cols || y0 < 0 || y0 >= rows) continue; // drawing off-screen
|
||||
if (((bits>>(j+(8-w))) & 0x01)) { // bit set
|
||||
setPixelColorXY(x0, y0, col);
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,13 @@ CRGBPalette16 Segment::_randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||
CRGBPalette16 Segment::_newRandomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||
unsigned long Segment::_lastPaletteChange = 0; // perhaps it should be per segment
|
||||
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
bool Segment::_modeBlend = false;
|
||||
#endif
|
||||
|
||||
// copy constructor
|
||||
Segment::Segment(const Segment &orig) {
|
||||
//DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
||||
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
transitional = false; // copied segment cannot be in transition
|
||||
name = nullptr;
|
||||
@ -92,12 +96,12 @@ Segment::Segment(const Segment &orig) {
|
||||
_t = nullptr;
|
||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||
//if (orig._t) { _t = new Transition(orig._t->_dur); }
|
||||
}
|
||||
|
||||
// move constructor
|
||||
Segment::Segment(Segment &&orig) noexcept {
|
||||
//DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
||||
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
orig.transitional = false; // old segment cannot be in transition any more
|
||||
orig.name = nullptr;
|
||||
@ -108,12 +112,17 @@ Segment::Segment(Segment &&orig) noexcept {
|
||||
|
||||
// copy assignment
|
||||
Segment& Segment::operator= (const Segment &orig) {
|
||||
//DEBUG_PRINTLN(F("-- Copying segment --"));
|
||||
//DEBUG_PRINTF("-- Copying segment: %p -> %p\n", &orig, this);
|
||||
if (this != &orig) {
|
||||
// clean destination
|
||||
transitional = false; // copied segment cannot be in transition
|
||||
if (name) delete[] name;
|
||||
if (_t) delete _t;
|
||||
if (_t) {
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
||||
#endif
|
||||
delete _t;
|
||||
}
|
||||
deallocateData();
|
||||
// copy source
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
@ -133,12 +142,18 @@ Segment& Segment::operator= (const Segment &orig) {
|
||||
|
||||
// move assignment
|
||||
Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||
//DEBUG_PRINTLN(F("-- Moving segment --"));
|
||||
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
||||
if (this != &orig) {
|
||||
transitional = false; // just temporary
|
||||
if (name) { delete[] name; name = nullptr; } // free old name
|
||||
deallocateData(); // free old runtime data
|
||||
if (_t) { delete _t; _t = nullptr; }
|
||||
if (_t) {
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
||||
#endif
|
||||
delete _t;
|
||||
_t = nullptr;
|
||||
}
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
orig.transitional = false; // old segment cannot be in transition
|
||||
orig.name = nullptr;
|
||||
@ -151,12 +166,18 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||
|
||||
bool Segment::allocateData(size_t len) {
|
||||
if (data && _dataLen == len) return true; //already allocated
|
||||
//DEBUG_PRINTF("-- Allocating data (%d): %p\n", len, this);
|
||||
deallocateData();
|
||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
|
||||
// not enough memory
|
||||
DEBUG_PRINTF("!!! Effect RAM depleted: %d/%d !!!\n", len, Segment::getUsedSegmentData());
|
||||
return false;
|
||||
}
|
||||
// do not use SPI RAM on ESP32 since it is slow
|
||||
data = (byte*) malloc(len);
|
||||
if (!data) return false; //allocation failed
|
||||
if (!data) { DEBUG_PRINTLN(F("!!! Allocation failed. !!!")); return false; } //allocation failed
|
||||
Segment::addUsedSegmentData(len);
|
||||
//DEBUG_PRINTF("--- Allocated data (%p): %d/%d -> %p\n", this, len, Segment::getUsedSegmentData(), data);
|
||||
_dataLen = len;
|
||||
memset(data, 0, len);
|
||||
return true;
|
||||
@ -164,9 +185,11 @@ bool Segment::allocateData(size_t len) {
|
||||
|
||||
void Segment::deallocateData() {
|
||||
if (!data) return;
|
||||
//DEBUG_PRINTF("--- Released data (%p): %d/%d -> %p\n", this, _dataLen, Segment::getUsedSegmentData(), data);
|
||||
free(data);
|
||||
data = nullptr;
|
||||
Segment::addUsedSegmentData(-_dataLen);
|
||||
// WARNING it looks like we have a memory leak somewhere
|
||||
Segment::addUsedSegmentData(_dataLen <= Segment::getUsedSegmentData() ? -_dataLen : -Segment::getUsedSegmentData());
|
||||
_dataLen = 0;
|
||||
}
|
||||
|
||||
@ -179,7 +202,7 @@ void Segment::deallocateData() {
|
||||
*/
|
||||
void Segment::resetIfRequired() {
|
||||
if (!reset) return;
|
||||
|
||||
//DEBUG_PRINTF("-- Segment reset: %p\n", this);
|
||||
deallocateData();
|
||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||
reset = false;
|
||||
@ -215,7 +238,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)));
|
||||
_lastPaletteChange = millis();
|
||||
handleRandomPalette(); // do initial blend
|
||||
handleRandomPalette(); // do a 1st pass of blend
|
||||
}
|
||||
targetPalette = _randomPalette;
|
||||
break;}
|
||||
@ -270,11 +293,8 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
|
||||
void Segment::startTransition(uint16_t dur) {
|
||||
if (!dur) {
|
||||
transitional = false;
|
||||
if (_t) {
|
||||
delete _t;
|
||||
_t = nullptr;
|
||||
}
|
||||
if (_t) _t->_dur = dur; // this will stop transition in next handleTransisiton()
|
||||
else transitional = false;
|
||||
return;
|
||||
}
|
||||
if (transitional && _t) return; // already in transition no need to store anything
|
||||
@ -283,44 +303,165 @@ void Segment::startTransition(uint16_t dur) {
|
||||
_t = new Transition(dur); // no previous transition running
|
||||
if (!_t) return; // failed to allocate data
|
||||
|
||||
//DEBUG_PRINTF("-- Started transition: %p\n", this);
|
||||
CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette);
|
||||
_t->_briT = on ? opacity : 0;
|
||||
_t->_cctT = cct;
|
||||
_t->_palT = _palT;
|
||||
_t->_modeP = mode;
|
||||
_t->_palT = _palT;
|
||||
_t->_briT = on ? opacity : 0;
|
||||
_t->_cctT = cct;
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
swapSegenv(_t->_segT);
|
||||
_t->_modeT = mode;
|
||||
_t->_segT._optionsT |= 0b0000000001000000; // mark old segment transitional
|
||||
_t->_segT._dataLenT = 0;
|
||||
_t->_segT._dataT = nullptr;
|
||||
if (_dataLen > 0 && data) {
|
||||
_t->_segT._dataT = (byte *)malloc(_dataLen);
|
||||
if (_t->_segT._dataT) {
|
||||
//DEBUG_PRINTF("-- Allocated duplicate data (%d): %p\n", _dataLen, _t->_segT._dataT);
|
||||
memcpy(_t->_segT._dataT, data, _dataLen);
|
||||
_t->_segT._dataLenT = _dataLen;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = colors[i];
|
||||
#endif
|
||||
transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true);
|
||||
}
|
||||
|
||||
void Segment::stopTransition() {
|
||||
if (!transitional) return;
|
||||
transitional = false; // finish transitioning segment
|
||||
//DEBUG_PRINTF("-- Stopping transition: %p\n", this);
|
||||
if (_t) {
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
||||
//DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT);
|
||||
free(_t->_segT._dataT);
|
||||
_t->_segT._dataT = nullptr;
|
||||
}
|
||||
#endif
|
||||
delete _t;
|
||||
_t = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Segment::handleTransition() {
|
||||
if (!transitional) return;
|
||||
uint16_t _progress = progress();
|
||||
if (_progress == 0xFFFFU) stopTransition();
|
||||
}
|
||||
|
||||
// transition progression between 0-65535
|
||||
uint16_t Segment::progress() {
|
||||
if (!transitional || !_t) return 0xFFFFU;
|
||||
unsigned long timeNow = millis();
|
||||
if (timeNow - _t->_start > _t->_dur || _t->_dur == 0) return 0xFFFFU;
|
||||
return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||
if (transitional && _t) {
|
||||
unsigned long timeNow = millis();
|
||||
if (_t->_dur > 0 && timeNow - _t->_start < _t->_dur) return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||
}
|
||||
return 0xFFFFU;
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
void Segment::swapSegenv(tmpsegd_t &tmpSeg) {
|
||||
if (!_t) return;
|
||||
//DEBUG_PRINTF("-- Saving temp seg: %p (%p)\n", this, tmpSeg);
|
||||
tmpSeg._optionsT = options;
|
||||
for (size_t i=0; i<NUM_COLORS; i++) tmpSeg._colorT[i] = colors[i];
|
||||
tmpSeg._speedT = speed;
|
||||
tmpSeg._intensityT = intensity;
|
||||
tmpSeg._custom1T = custom1;
|
||||
tmpSeg._custom2T = custom2;
|
||||
tmpSeg._custom3T = custom3;
|
||||
tmpSeg._check1T = check1;
|
||||
tmpSeg._check2T = check2;
|
||||
tmpSeg._check3T = check3;
|
||||
tmpSeg._aux0T = aux0;
|
||||
tmpSeg._aux1T = aux1;
|
||||
tmpSeg._stepT = step;
|
||||
tmpSeg._callT = call;
|
||||
tmpSeg._dataT = data;
|
||||
tmpSeg._dataLenT = _dataLen;
|
||||
if (&tmpSeg != &(_t->_segT)) {
|
||||
// swap SEGENV with transitional data
|
||||
options = _t->_segT._optionsT;
|
||||
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = _t->_segT._colorT[i];
|
||||
speed = _t->_segT._speedT;
|
||||
intensity = _t->_segT._intensityT;
|
||||
custom1 = _t->_segT._custom1T;
|
||||
custom2 = _t->_segT._custom2T;
|
||||
custom3 = _t->_segT._custom3T;
|
||||
check1 = _t->_segT._check1T;
|
||||
check2 = _t->_segT._check2T;
|
||||
check3 = _t->_segT._check3T;
|
||||
aux0 = _t->_segT._aux0T;
|
||||
aux1 = _t->_segT._aux1T;
|
||||
step = _t->_segT._stepT;
|
||||
call = _t->_segT._callT;
|
||||
data = _t->_segT._dataT;
|
||||
_dataLen = _t->_segT._dataLenT;
|
||||
}
|
||||
//DEBUG_PRINTF("-- temp seg data: %p (%d,%p)\n", this, _dataLen, data);
|
||||
}
|
||||
|
||||
void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
|
||||
//DEBUG_PRINTF("-- Restoring temp seg: %p (%p)\n", this, tmpSeg);
|
||||
if (_t && &(_t->_segT) != &tmpSeg) {
|
||||
// update possibly changed variables to keep old effect running correctly
|
||||
_t->_segT._aux0T = aux0;
|
||||
_t->_segT._aux1T = aux1;
|
||||
_t->_segT._stepT = step;
|
||||
_t->_segT._callT = call;
|
||||
//if (_t->_segT._dataT != data) DEBUG_PRINTF("--- data re-allocated: (%p) %p -> %p\n", this, _t->_segT._dataT, data);
|
||||
_t->_segT._dataT = data; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
||||
_t->_segT._dataLenT = _dataLen; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
||||
}
|
||||
options = tmpSeg._optionsT;
|
||||
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg._colorT[i];
|
||||
speed = tmpSeg._speedT;
|
||||
intensity = tmpSeg._intensityT;
|
||||
custom1 = tmpSeg._custom1T;
|
||||
custom2 = tmpSeg._custom2T;
|
||||
custom3 = tmpSeg._custom3T;
|
||||
check1 = tmpSeg._check1T;
|
||||
check2 = tmpSeg._check2T;
|
||||
check3 = tmpSeg._check3T;
|
||||
aux0 = tmpSeg._aux0T;
|
||||
aux1 = tmpSeg._aux1T;
|
||||
step = tmpSeg._stepT;
|
||||
call = tmpSeg._callT;
|
||||
data = tmpSeg._dataT;
|
||||
_dataLen = tmpSeg._dataLenT;
|
||||
//DEBUG_PRINTF("-- temp seg data: %p (%d,%p)\n", this, _dataLen, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
|
||||
uint32_t prog = progress();
|
||||
if (transitional && _t && prog < 0xFFFFU) {
|
||||
if (prog < 0xFFFFU) {
|
||||
if (useCct) return ((briNew * prog) + _t->_cctT * (0xFFFFU - prog)) >> 16;
|
||||
else return ((briNew * prog) + _t->_briT * (0xFFFFU - prog)) >> 16;
|
||||
} else {
|
||||
return briNew;
|
||||
}
|
||||
return briNew;
|
||||
}
|
||||
|
||||
uint8_t Segment::currentMode(uint8_t newMode) {
|
||||
return (progress()>32767U) ? newMode : _t->_modeP; // change effect in the middle of transition
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
uint16_t prog = progress(); // implicit check for transitional & _t in progress()
|
||||
if (prog < 0xFFFFU) return _t->_modeT;
|
||||
#endif
|
||||
return newMode;
|
||||
}
|
||||
|
||||
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
return transitional && _t ? color_blend(_t->_segT._colorT[slot], colorNew, progress(), true) : colorNew;
|
||||
#else
|
||||
return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
|
||||
#endif
|
||||
}
|
||||
|
||||
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
loadPalette(targetPalette, pal);
|
||||
if (transitional && _t && progress() < 0xFFFFU) {
|
||||
if (progress() < 0xFFFFU) {
|
||||
// blend palettes
|
||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||
// minimum blend time is 100ms maximum is 65535ms
|
||||
@ -332,18 +473,6 @@ CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal
|
||||
return targetPalette;
|
||||
}
|
||||
|
||||
void Segment::handleTransition() {
|
||||
if (!transitional) return;
|
||||
uint16_t _progress = progress();
|
||||
if (_progress == 0xFFFFU) transitional = false; // finish transitioning segment
|
||||
if (_t) { // thanks to @nXm AKA https://github.com/NMeirer
|
||||
if (_progress == 0xFFFFU) {
|
||||
delete _t;
|
||||
_t = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// relies on WS2812FX::service() to call it max every 8ms or more (MIN_SHOW_DELAY)
|
||||
void Segment::handleRandomPalette() {
|
||||
// just do a blend; if the palettes are identical it will just compare 48 bytes (same as _randomPalette == _newRandomPalette)
|
||||
@ -426,6 +555,7 @@ void Segment::setCCT(uint16_t k) {
|
||||
void Segment::setOpacity(uint8_t o) {
|
||||
if (opacity == o) return;
|
||||
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
||||
DEBUG_PRINT(F("-- Setting opacity: ")); DEBUG_PRINTLN(o);
|
||||
opacity = o;
|
||||
stateChanged = true; // send UDP/WS broadcast
|
||||
}
|
||||
@ -444,7 +574,6 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
||||
if (fx != mode) {
|
||||
if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions
|
||||
mode = fx;
|
||||
|
||||
// load default values from effect string
|
||||
if (loadDefaults) {
|
||||
int16_t sOpt;
|
||||
@ -625,6 +754,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
}
|
||||
i += start; // starting pixel in a group
|
||||
|
||||
uint32_t tmpCol = col;
|
||||
// set all the pixels in the group
|
||||
for (int j = 0; j < grouping; j++) {
|
||||
uint16_t indexSet = i + ((reverse) ? -j : j);
|
||||
@ -633,11 +763,17 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
uint16_t indexMir = stop - indexSet + start - 1;
|
||||
indexMir += offset; // offset/phase
|
||||
if (indexMir >= stop) indexMir -= len; // wrap
|
||||
strip.setPixelColor(indexMir, col);
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexMir), col, 0xFFFFU - progress(), true);
|
||||
#endif
|
||||
strip.setPixelColor(indexMir, tmpCol);
|
||||
}
|
||||
indexSet += offset; // offset/phase
|
||||
if (indexSet >= stop) indexSet -= len; // wrap
|
||||
strip.setPixelColor(indexSet, col);
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (_modeBlend) tmpCol = color_blend(strip.getPixelColor(indexSet), col, 0xFFFFU - progress(), true);
|
||||
#endif
|
||||
strip.setPixelColor(indexSet, tmpCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -843,7 +979,7 @@ void Segment::fade_out(uint8_t rate) {
|
||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
|
||||
rate = (255-rate) >> 1;
|
||||
float mappedRate = float(rate) +1.1;
|
||||
float mappedRate = float(rate) +1.1f;
|
||||
|
||||
uint32_t color = colors[1]; // SEGCOLOR(1); // target color
|
||||
int w2 = W(color);
|
||||
@ -1079,8 +1215,10 @@ void WS2812FX::service() {
|
||||
// reset the segment runtime data if needed
|
||||
seg.resetIfRequired();
|
||||
|
||||
if (!seg.isActive()) continue;
|
||||
|
||||
// last condition ensures all solid segments are updated at the same time
|
||||
if (seg.isActive() && (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)))
|
||||
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
||||
{
|
||||
doShow = true;
|
||||
uint16_t delay = FRAMETIME;
|
||||
@ -1095,10 +1233,25 @@ void WS2812FX::service() {
|
||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
||||
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
||||
|
||||
// effect blending (execute previous effect)
|
||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||
delay = (*_mode[seg.currentMode(seg.mode)])();
|
||||
// Effect blending
|
||||
// When two effects are being blended, each may have different segment data, this
|
||||
// data needs to be saved first and then restored before running previous/transitional mode.
|
||||
// The blending will largely depend on the effect behaviour since actual output (LEDs) may be
|
||||
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
|
||||
// would need to be allocated for each effect and then blended together for each pixel.
|
||||
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(seg.mode); // this will return old mode while in transition
|
||||
delay = (*_mode[seg.mode])(); // run new/current mode
|
||||
#ifndef WLED_DISABLE_MODE_BLEND
|
||||
if (seg.mode != tmpMode) {
|
||||
Segment::tmpsegd_t _tmpSegData;
|
||||
Segment::modeBlend(true); // set semaphore
|
||||
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
||||
uint16_t d2 = (*_mode[tmpMode])(); // run old mode
|
||||
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state)
|
||||
delay = MIN(delay,d2); // use shortest delay
|
||||
Segment::modeBlend(false); // unset semaphore
|
||||
}
|
||||
#endif
|
||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
||||
}
|
||||
@ -1273,9 +1426,7 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||
if (m >= getModeCount()) m = getModeCount() - 1;
|
||||
|
||||
if (_segments[segid].mode != m) {
|
||||
_segments[segid].startTransition(_transitionDur); // set effect transitions
|
||||
_segments[segid].markForReset();
|
||||
_segments[segid].mode = m;
|
||||
_segments[segid].setMode(m); // do not load defaults
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,10 @@ void BusDigital::show() {
|
||||
pix += _skip;
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
#if !defined(STATUSLED) || STATUSLED>=0
|
||||
if (_skip) PolyBus::setPixelColor(_busPtr, _iType, 0, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
||||
#endif
|
||||
for (int i=1; i<_skip; i++) PolyBus::setPixelColor(_busPtr, _iType, i, 0, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); // paint skipped pixels black
|
||||
}
|
||||
PolyBus::show(_busPtr, _iType, !_buffering); // faster if buffer consistency is not important
|
||||
}
|
||||
|
@ -29,8 +29,11 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
||||
}
|
||||
|
||||
//DEBUG_PRINTLN("-- JSON deserialize segment.");
|
||||
Segment& seg = strip.getSegment(id);
|
||||
//DEBUG_PRINTF("-- Original segment: %p\n", &seg);
|
||||
Segment prev = seg; //make a backup so we can tell if something changed
|
||||
//DEBUG_PRINTF("-- Duplicate segment: %p\n", &prev);
|
||||
|
||||
uint16_t start = elem["start"] | seg.start;
|
||||
if (stop < 0) {
|
||||
@ -979,9 +982,10 @@ void serializeNodes(JsonObject root)
|
||||
// deserializes mode data string into JsonArray
|
||||
void serializeModeData(JsonArray fxdata)
|
||||
{
|
||||
char lineBuffer[128];
|
||||
char lineBuffer[256];
|
||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||
strncpy_P(lineBuffer, strip.getModeData(i), 127);
|
||||
strncpy_P(lineBuffer, strip.getModeData(i), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
if (lineBuffer[0] != 0) {
|
||||
char* dataPtr = strchr(lineBuffer,'@');
|
||||
if (dataPtr) fxdata.add(dataPtr+1);
|
||||
@ -992,10 +996,12 @@ void serializeModeData(JsonArray fxdata)
|
||||
|
||||
// deserializes mode names string into JsonArray
|
||||
// also removes effect data extensions (@...) from deserialised names
|
||||
void serializeModeNames(JsonArray arr) {
|
||||
char lineBuffer[128];
|
||||
void serializeModeNames(JsonArray arr)
|
||||
{
|
||||
char lineBuffer[256];
|
||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||
strncpy_P(lineBuffer, strip.getModeData(i), 127);
|
||||
strncpy_P(lineBuffer, strip.getModeData(i), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
if (lineBuffer[0] != 0) {
|
||||
char* dataPtr = strchr(lineBuffer,'@');
|
||||
if (dataPtr) *dataPtr = 0; // terminate mode data after name
|
||||
|
@ -37,12 +37,12 @@ void applyValuesToSelectedSegs()
|
||||
|
||||
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
||||
if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
|
||||
if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette); stateChanged = true;}
|
||||
if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent); stateChanged = true;}
|
||||
if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette);}
|
||||
if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent);}
|
||||
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
||||
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
|
||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
|
||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0);}
|
||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1);}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,8 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
||||
if (mode < strip.getModeCount()) {
|
||||
char lineBuffer[256];
|
||||
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
||||
strcpy_P(lineBuffer, strip.getModeData(mode));
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
size_t len = strlen(lineBuffer);
|
||||
size_t j = 0;
|
||||
for (; j < maxLen && j < len; j++) {
|
||||
@ -367,9 +368,9 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||
{
|
||||
if (mode < strip.getModeCount()) {
|
||||
char lineBuffer[128] = "";
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), 127);
|
||||
lineBuffer[127] = '\0'; // terminate string
|
||||
char lineBuffer[256];
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
if (lineBuffer[0] != 0) {
|
||||
char* startPtr = strrchr(lineBuffer, ';'); // last ";" in FX data
|
||||
if (!startPtr) return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user