diff --git a/.gitignore b/.gitignore index d8884449..2116e693 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ .pioenvs .piolibdeps .vscode -platformio.ini !.vscode/extensions.json /wled00/Release /wled00/extLibs diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 867ef9f1..2bdb75ba 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -262,7 +262,7 @@ uint16_t WS2812FX::mode_dynamic(void) { */ uint16_t WS2812FX::mode_breath(void) { uint16_t var = 0; - uint16_t counter = (now * ((SEGMENT.speed >> 3) +10)) & 0xFFFF; + uint16_t counter = (now * ((SEGMENT.speed >> 3) +10)); counter = (counter >> 2) + (counter >> 4); //0-16384 + 0-2048 if (counter < 16384) { if (counter > 8192) counter = 8192 - (counter - 8192); @@ -282,9 +282,8 @@ uint16_t WS2812FX::mode_breath(void) { * Fades the LEDs between two colors */ uint16_t WS2812FX::mode_fade(void) { - uint16_t counter = (now * ((SEGMENT.speed >> 3) +10)) & 0xFFFF; - if (counter > 32767) counter = 32768 - (counter - 32768); - uint8_t lum = counter >> 7; + uint16_t counter = (now * ((SEGMENT.speed >> 3) +10)); + uint8_t lum = triwave16(counter) >> 8; for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), lum)); @@ -1100,182 +1099,56 @@ uint16_t WS2812FX::mode_loading(void) { } -/* - * Lights all LEDs after each other up starting from the outer edges and - * finishing in the middle. Then turns them in reverse order off. Repeat. - */ -uint16_t WS2812FX::mode_dual_color_wipe_in_out(void) { - int end = SEGLEN - SEGENV.step - 1; - bool odd = (SEGLEN % 2) == 1; - int mid = odd ? ((SEGLEN / 2) + 1) : (SEGLEN / 2); - if (SEGENV.step < mid) { - byte pindex = map(SEGENV.step, 0, mid -1, 0, 255); - uint32_t col = color_from_palette(pindex, false, false, 0); - - setPixelColor(SEGMENT.start + SEGENV.step, col); - setPixelColor(SEGMENT.start + end, col); - } else { - if (odd) { - // If odd, we need to 'double count' the center LED (once to turn it on, - // once to turn it off). So trail one behind after the middle LED. - setPixelColor(SEGMENT.start + SEGENV.step - 1, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + end + 1, SEGCOLOR(1)); - } else { - setPixelColor(SEGMENT.start + SEGENV.step, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + end, SEGCOLOR(1)); - } - } - SEGENV.step++; - if (odd) { - if (SEGENV.step > SEGLEN) { - SEGENV.step = 0; - } - } else { - if (SEGENV.step >= SEGLEN) { - SEGENV.step = 0; - } - } - return SPEED_FORMULA_L; +//American Police Light with all LEDs Red and Blue +uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2) +{ + uint16_t counter = now * ((SEGMENT.speed >> 3) +1); + uint16_t idexR = (counter * SEGLEN) >> 16; + if (idexR >= SEGLEN) idexR = 0; + + uint16_t topindex = SEGLEN >> 1; + uint16_t idexB = idexR + topindex; + + if (idexR > topindex) idexB -= SEGLEN; + if (idexB >= SEGLEN) idexB = 0; //otherwise overflow on odd number of LEDs + + setPixelColor(SEGMENT.start + idexR, color1); + setPixelColor(SEGMENT.start + idexB, color2); + + return FRAMETIME; } -/* -* Lights all LEDs after each other up starting from the outer edges and -* finishing in the middle. Then turns them in that order off. Repeat. -*/ -uint16_t WS2812FX::mode_dual_color_wipe_in_in(void) { - bool odd = (SEGLEN % 2) == 1; - int mid = SEGLEN / 2; - byte pindex = 0; - uint32_t col = 0; - if (SEGENV.step <= mid) - { - pindex = map(SEGENV.step, 0, mid, 0, 255); - col = color_from_palette(pindex, false, false, 0); - } - if (odd) { - if (SEGENV.step <= mid) { - setPixelColor(SEGMENT.start + SEGENV.step, col); - setPixelColor(SEGMENT.start + SEGLEN - SEGENV.step - 1, col); - } else { - int i = SEGENV.step - mid; - setPixelColor(SEGMENT.start + i - 1, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + SEGLEN - i, SEGCOLOR(1)); - } - } else { - if (SEGENV.step < mid) { - setPixelColor(SEGMENT.start + SEGENV.step, col); - setPixelColor(SEGMENT.start + SEGLEN - SEGENV.step - 1, col); - } else { - int i = SEGENV.step - mid; - setPixelColor(SEGMENT.start + i, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + SEGLEN - i - 1, SEGCOLOR(1)); - } - } - SEGENV.step++; - if (odd) { - if (SEGENV.step > SEGLEN) { - SEGENV.step = 0; - } - } else { - if (SEGENV.step >= SEGLEN) { - SEGENV.step = 0; - } - } - return SPEED_FORMULA_L; +//American Police Light with all LEDs Red and Blue +uint16_t WS2812FX::mode_police_all() +{ + return police_base(RED, BLUE); } -/* -* Lights all LEDs after each other up starting from the middle and -* finishing at the edges. Then turns them off in that order. Repeat. -*/ -uint16_t WS2812FX::mode_dual_color_wipe_out_out(void) { - int end = SEGLEN - SEGENV.step - 1; - bool odd = (SEGLEN % 2) == 1; - int mid = SEGLEN / 2; - byte pindex = 0; - uint32_t col = 0; - if (SEGENV.step <= mid) - { - pindex = map(SEGENV.step, 0, mid, 255, 0); - col = color_from_palette(pindex, false, false, 0); - } - if (odd) { - if (SEGENV.step <= mid) { - setPixelColor(SEGMENT.start + mid + SEGENV.step, col); - setPixelColor(SEGMENT.start + mid - SEGENV.step, col); - } else { - setPixelColor(SEGMENT.start + SEGENV.step - 1, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + end + 1, SEGCOLOR(1)); - } - } else { - if (SEGENV.step < mid) { - setPixelColor(SEGMENT.start + mid - SEGENV.step - 1, col); - setPixelColor(SEGMENT.start + mid + SEGENV.step, col); - } else { - setPixelColor(SEGMENT.start + SEGENV.step, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + end, SEGCOLOR(1)); - } - } - SEGENV.step++; - if (odd) { - if (SEGENV.step > SEGLEN) { - SEGENV.step = 0; - } - } else { - if (SEGENV.step >= SEGLEN) { - SEGENV.step = 0; - } - } - return SPEED_FORMULA_L; -} +//Police Lights Red and Blue +uint16_t WS2812FX::mode_police() +{ + fill(SEGCOLOR(1)); + + return police_base(RED, BLUE); +} -/* -* Lights all LEDs after each other up starting from the middle and -* finishing at the edges. Then turns them off in reverse order. Repeat. -*/ -uint16_t WS2812FX::mode_dual_color_wipe_out_in(void) { - bool odd = (SEGLEN % 2) == 1; - int mid = SEGLEN / 2; - byte pindex = 0; - uint32_t col = 0; - if (SEGENV.step <= mid) - { - pindex = map(SEGENV.step, 0, mid, 255, 0); - col = color_from_palette(pindex, false, false, 0); - } - if (odd) { - if (SEGENV.step <= mid) { - setPixelColor(SEGMENT.start + mid + SEGENV.step, col); - setPixelColor(SEGMENT.start + mid - SEGENV.step, col); - } else { - int i = SEGENV.step - mid; - setPixelColor(SEGMENT.start + i - 1, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + SEGLEN - i, SEGCOLOR(1)); - } - } else { - if (SEGENV.step < mid) { - setPixelColor(SEGMENT.start + mid - SEGENV.step - 1, col); - setPixelColor(SEGMENT.start + mid + SEGENV.step, col); - } else { - int i = SEGENV.step - mid; - setPixelColor(SEGMENT.start + i, SEGCOLOR(1)); - setPixelColor(SEGMENT.start + SEGLEN - i - 1, SEGCOLOR(1)); - } - } - SEGENV.step++; - if (odd) { - if (SEGENV.step > SEGLEN) { - SEGENV.step = 0; - } - } else { - if (SEGENV.step >= SEGLEN) { - SEGENV.step = 0; - } - } - return SPEED_FORMULA_L; +//Police All with custom colors +uint16_t WS2812FX::mode_two_areas() +{ + return police_base(SEGCOLOR(0), SEGCOLOR(1)); +} + + +//Police Lights with custom colors +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); } @@ -2197,7 +2070,7 @@ CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) // "CalculateOneTwinkle" on each pixel. It then displays // either the twinkle color of the background color, // whichever is brighter. -void WS2812FX::twinklefox_base(bool cat) +uint16_t WS2812FX::twinklefox_base(bool cat) { // "PRNG16" is the pseudorandom number generator // It MUST be reset to the same starting value each time @@ -2253,18 +2126,17 @@ void WS2812FX::twinklefox_base(bool cat) setPixelColor(i, bg.r, bg.g, bg.b); } } + return FRAMETIME; } uint16_t WS2812FX::mode_twinklefox() { - twinklefox_base(false); - return FRAMETIME; + return twinklefox_base(false); } uint16_t WS2812FX::mode_twinklecat() { - twinklefox_base(true); - return FRAMETIME; + return twinklefox_base(true); } @@ -2370,41 +2242,46 @@ uint16_t WS2812FX::mode_tri_static_pattern() return FRAMETIME; } -//American Police Light with all LEDs Red and Blue -uint16_t WS2812FX::mode_policeall() -{ - SEGENV.step++; - if (SEGENV.step >= SEGLEN) { - SEGENV.step = 0; - } - uint16_t idexR = SEGENV.step; - uint16_t topindex = SEGLEN >> 1; - uint16_t idexB = idexR + topindex; - - if (idexR >= topindex) idexB -= SEGLEN; - - setPixelColor(idexR, RED); - setPixelColor(idexB, BLUE); - - return SPEED_FORMULA_L; -} - - -//Police Lights Red and Blue -uint16_t WS2812FX::mode_police() +uint16_t WS2812FX::spots_base(uint16_t threshold) { fill(SEGCOLOR(1)); + + uint16_t maxZones = SEGLEN >> 2; + uint16_t zones = 1 + ((SEGMENT.intensity * maxZones) >> 8); + uint16_t zoneLen = SEGLEN / zones; + uint16_t offset = (SEGLEN - zones * zoneLen) >> 1; - return mode_policeall(); + for (uint16_t z = 0; z < zones; z++) + { + uint16_t pos = offset + z * zoneLen; + for (uint16_t i = 0; i < zoneLen; i++) + { + uint16_t wave = triwave16((i * 0xFFFF) / zoneLen); + if (wave > threshold) { + uint16_t index = SEGMENT.start + pos + i; + uint8_t s = (wave - threshold)*255 / (0xFFFF - threshold); + setPixelColor(index, color_blend(color_from_palette(index, true, PALETTE_SOLID_WRAP, 0), SEGCOLOR(1), 255-s)); + } + } + } + + return FRAMETIME; } -//Speed slider sets number of "lights", intensity sets LEDs per light -/*uint16_t WS2812FX::mode_static_pattern2() +//Intensity slider sets number of "lights", speed sets LEDs per light +uint16_t WS2812FX::mode_spots() { - uint16_t maxlights = SEGLEN >> 1; - uint16_t zones = 1 + (SEGMENT.speed); - - return FRAMETIME; -}*/ + return spots_base((255 - SEGMENT.speed) << 8); +} + + +//Intensity slider sets number of "lights", LEDs per light fade in and out +uint16_t WS2812FX::mode_spots_fade() +{ + uint16_t counter = now * ((SEGMENT.speed >> 2) +8); + uint16_t t = triwave16(counter); + uint16_t tr = (t >> 1) + (t >> 2); + return spots_base(tr); +} diff --git a/wled00/FX.h b/wled00/FX.h index 4a5caa49..d6bb85a8 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -134,10 +134,10 @@ #define FX_MODE_FIRE_FLICKER 45 #define FX_MODE_GRADIENT 46 #define FX_MODE_LOADING 47 -#define FX_MODE_DUAL_COLOR_WIPE_IN_OUT 48 -#define FX_MODE_DUAL_COLOR_WIPE_IN_IN 49 -#define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50 -#define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51 +#define FX_MODE_POLICE 48 +#define FX_MODE_POLICE_ALL 49 +#define FX_MODE_TWO_DOTS 50 +#define FX_MODE_TWO_AREAS 51 #define FX_MODE_CIRCUS_COMBUSTUS 52 #define FX_MODE_HALLOWEEN 53 #define FX_MODE_TRICOLOR_CHASE 54 @@ -149,7 +149,6 @@ #define FX_MODE_DUAL_LARSON_SCANNER 60 #define FX_MODE_RANDOM_CHASE 61 #define FX_MODE_OSCILLATE 62 -//Modes that use FastLED --> #define FX_MODE_PRIDE_2015 63 #define FX_MODE_JUGGLE 64 #define FX_MODE_PALETTE 65 @@ -172,8 +171,8 @@ #define FX_MODE_HALLOWEEN_EYES 82 #define FX_MODE_STATIC_PATTERN 83 #define FX_MODE_TRI_STATIC_PATTERN 84 -#define FX_MODE_POLICE 85 -#define FX_MODE_POLICE_ALL 86 +#define FX_MODE_SPOTS 85 +#define FX_MODE_SPOTS_FADE 86 class WS2812FX { @@ -277,10 +276,10 @@ class WS2812FX { _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; _mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient; _mode[FX_MODE_LOADING] = &WS2812FX::mode_loading; - _mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out; - _mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in; - _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out; - _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in; + _mode[FX_MODE_POLICE] = &WS2812FX::mode_police; + _mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_police_all; + _mode[FX_MODE_TWO_DOTS] = &WS2812FX::mode_two_dots; + _mode[FX_MODE_TWO_AREAS] = &WS2812FX::mode_two_areas; _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween; _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; @@ -316,8 +315,8 @@ class WS2812FX { _mode[FX_MODE_HALLOWEEN_EYES] = &WS2812FX::mode_halloween_eyes; _mode[FX_MODE_STATIC_PATTERN] = &WS2812FX::mode_static_pattern; _mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern; - _mode[FX_MODE_POLICE] = &WS2812FX::mode_police; - _mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_policeall; + _mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots; + _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -387,6 +386,7 @@ class WS2812FX { uint16_t ablMilliampsMax, currentMilliamps, + triwave16(uint16_t), getUsableCount(); uint32_t @@ -459,10 +459,10 @@ class WS2812FX { mode_fire_flicker(void), mode_gradient(void), mode_loading(void), - mode_dual_color_wipe_in_out(void), - mode_dual_color_wipe_in_in(void), - mode_dual_color_wipe_out_out(void), - mode_dual_color_wipe_out_in(void), + mode_police(void), + mode_police_all(void), + mode_two_dots(void), + mode_two_areas(void), mode_circus_combustus(void), mode_bicolor_chase(void), mode_tricolor_chase(void), @@ -496,8 +496,8 @@ class WS2812FX { mode_halloween_eyes(void), mode_static_pattern(void), mode_tri_static_pattern(void), - mode_police(void), - mode_policeall(void); + mode_spots(void), + mode_spots_fade(void); private: NeoPixelWrapper *bus; @@ -515,7 +515,6 @@ class WS2812FX { void handle_palette(void); void fill(uint32_t); bool modeUsesLock(uint8_t); - void twinklefox_base(bool); bool _modeUsesLock, @@ -540,8 +539,11 @@ class WS2812FX { dissolve(uint32_t), chase(uint32_t, uint32_t, uint32_t, bool), gradient_base(bool), + police_base(uint32_t, uint32_t), running(uint32_t, uint32_t), - tricolor_chase(uint32_t, uint32_t); + tricolor_chase(uint32_t, uint32_t), + twinklefox_base(bool), + spots_base(uint16_t); CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat); @@ -564,11 +566,11 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Scan","Dual Scan","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", "Sparkle","Dark Sparkle","Sparkle+","Strobe","Strobe Rainbow","Mega Strobe","Blink Rainbow","Android","Chase","Chase Random", "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", -"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","In Out","In In", -"Out Out","Out In","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", +"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All", +"Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Tri Color Pattern", "Police","Police All" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade" ])====="; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 8bd05857..b887332f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -645,6 +645,12 @@ void WS2812FX::blur(uint8_t blur_amount) } } +uint16_t WS2812FX::triwave16(uint16_t in) +{ + if (in < 0x8000) return in *2; + return 0xFFFF - (in - 0x8000)*2; +} + /* * Put a value 0 to 255 in to get a color value. * The colours are a transition r -> g -> b -> back to r diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 548314fb..0afd2d18 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -97,7 +97,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912033 +#define VERSION 1912042 char versionString[] = "0.8.7-dev"; diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino index 22f83188..a2c5fa6c 100644 --- a/wled00/wled19_json.ino +++ b/wled00/wled19_json.ino @@ -169,7 +169,6 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id) root["pal"] = seg.palette; root["sel"] = seg.isSelected(); root["rev"] = seg.getOption(1); - root["cln"] = -1; } @@ -217,6 +216,7 @@ void serializeInfo(JsonObject root) JsonObject leds = root.createNestedObject("leds"); leds["count"] = ledCount; leds["rgbw"] = useRGBW; + leds["wv"] = useRGBW && !autoRGBtoRGBW; //should a white channel slider be displayed? JsonArray leds_pin = leds.createNestedArray("pin"); leds_pin.add(LEDPIN);