diff --git a/platformio.ini b/platformio.ini index 47d6e9b5..ee227904 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,7 +12,7 @@ ; default_envs = travis_esp8266, travis_esp32 # Release binaries -default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32_eth_ota1mapp, esp32s2_saola, esp32c3 +default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32s2_saola, esp32c3 # Build everything ; default_envs = esp32dev, esp8285_4CH_MagicHome, codm-controller-0.6-rev2, codm-controller-0.6, esp32s2_saola, d1_mini_5CH_Shojo_PCB, d1_mini, sp501e, travis_esp8266, travis_esp32, nodemcuv2, esp32_eth, anavi_miracle_controller, esp07, esp01_1m_full, m5atom, h803wf, d1_mini_ota, heltec_wifi_kit_8, esp8285_H801, d1_mini_debug, wemos_shield_esp32, elekstube_ips @@ -206,9 +206,11 @@ lib_deps = makuna/NeoPixelBus @ 2.6.9 # 2.6.5/2.6.6 and newer do not compile on ESP core < 3.0.0 [esp32] -#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2/platform-tasmota-espressif32-2.0.2.zip +#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip platform = espressif32@3.5.0 +platform_packages = framework-arduinoespressif32 @ https://github.com/Aircoookie/arduino-esp32.git#1.0.6.4 + build_flags = -g -DARDUINO_ARCH_ESP32 #-DCONFIG_LITTLEFS_FOR_IDF_3_2 @@ -322,8 +324,9 @@ lib_deps = ${esp8266.lib_deps} [env:esp32dev] board = esp32dev platform = ${esp32.platform} +platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET lib_deps = ${esp32.lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.default_partitions} @@ -331,17 +334,13 @@ board_build.partitions = ${esp32.default_partitions} [env:esp32_eth] board = esp32-poe platform = ${esp32.platform} +platform_packages = ${esp32.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 lib_deps = ${esp32.lib_deps} board_build.partitions = ${esp32.default_partitions} -# ESP32 ETH build that fits in old 1M app space (disables Blynk and Hue sync) -[env:esp32_eth_ota1mapp] -extends = env:esp32_eth -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet_OTA -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC - [env:esp32s2_saola] board = esp32-s2-saola-1 platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 54f3669e..273541a0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2346,7 +2346,7 @@ uint16_t WS2812FX::mode_ripple_rainbow(void) { // incandescent bulbs change color as they get dim down. #define COOL_LIKE_INCANDESCENT 1 -CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) +CRGB IRAM_ATTR WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat) { // Overall twinkle speed (changed) uint16_t ticks = ms / SEGENV.aux0; diff --git a/wled00/FX.h b/wled00/FX.h index 2d5f35f1..b4132289 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -625,7 +625,7 @@ class WS2812FX { setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setColor(uint8_t slot, uint32_t c), setCCT(uint16_t k), - setBrightness(uint8_t b), + setBrightness(uint8_t b, bool direct = false), setRange(uint16_t i, uint16_t i2, uint32_t col), setShowCallback(show_callback cb), setTransition(uint16_t t), @@ -672,10 +672,10 @@ class WS2812FX { gamma8_cal(uint8_t, float), get_random_wheel_index(uint8_t); - inline uint8_t sin_gap(uint16_t in) { - if (in & 0x100) return 0; - return sin8(in + 192); //correct phase shift of sine so that it starts and stops at 0 - } + inline uint8_t sin_gap(uint16_t in) { + if (in & 0x100) return 0; + return sin8(in + 192); // correct phase shift of sine so that it starts and stops at 0 + } int8_t tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 5bc8c4e9..f81a46e6 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -133,7 +133,8 @@ void WS2812FX::service() { if (!SEGMENT.isActive()) continue; - if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary + // last condition ensures all solid segments are updated at the same time + if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) { if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check doShow = true; @@ -421,7 +422,7 @@ void WS2812FX::setCCT(uint16_t k) { } } -void WS2812FX::setBrightness(uint8_t b) { +void WS2812FX::setBrightness(uint8_t b, bool direct) { if (gammaCorrectBri) b = gamma8(b); if (_brightness == b) return; _brightness = b; @@ -431,8 +432,13 @@ void WS2812FX::setBrightness(uint8_t b) { _segments[i].setOption(SEG_OPTION_FREEZE, false); } } - unsigned long t = millis(); - if (_segment_runtimes[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon + if (direct) { + // would be dangerous if applied immediately (could exceed ABL), but will not output until the next show() + busses.setBrightness(b); + } else { + unsigned long t = millis(); + if (_segment_runtimes[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon + } } uint8_t WS2812FX::getBrightness(void) { diff --git a/wled00/e131.cpp b/wled00/e131.cpp index ba9e939e..6f7f193b 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -111,7 +111,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ return; // nothing to do break; - case DMX_MODE_SINGLE_RGB: + case DMX_MODE_SINGLE_RGB: // RGB only if (uni != e131Universe) return; if (dmxChannels-DMXAddress+1 < 3) return; realtimeLock(realtimeTimeoutMs, mde); @@ -121,7 +121,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel); break; - case DMX_MODE_SINGLE_DRGB: + case DMX_MODE_SINGLE_DRGB: // Dimmer + RGB if (uni != e131Universe) return; if (dmxChannels-DMXAddress+1 < 4) return; realtimeLock(realtimeTimeoutMs, mde); @@ -130,15 +130,19 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ if (DMXOldDimmer != e131_data[DMXAddress+0]) { DMXOldDimmer = e131_data[DMXAddress+0]; bri = e131_data[DMXAddress+0]; - strip.setBrightness(bri); + strip.setBrightness(bri, true); } for (uint16_t i = 0; i < totalLen; i++) setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel); break; - case DMX_MODE_EFFECT: + case DMX_MODE_EFFECT: // Length 1: Apply Preset ID, length 11-13: apply effect config if (uni != e131Universe) return; - if (dmxChannels-DMXAddress+1 < 11) return; + if (dmxChannels-DMXAddress+1 < 11) { + if (dmxChannels-DMXAddress+1 > 1) return; + applyPreset(e131_data[DMXAddress+0], CALL_MODE_NOTIFICATION); + return; + } if (DMXOldDimmer != e131_data[DMXAddress+0]) { DMXOldDimmer = e131_data[DMXAddress+0]; bri = e131_data[DMXAddress+0]; @@ -180,7 +184,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ previousLeds = 0; // First DMX address is dimmer in DMX_MODE_MULTIPLE_DRGB mode. if (DMXMode == DMX_MODE_MULTIPLE_DRGB) { - strip.setBrightness(e131_data[dmxOffset++]); + strip.setBrightness(e131_data[dmxOffset++], true); } } else { // All subsequent universes start at the first channel. diff --git a/wled00/json.cpp b/wled00/json.cpp index 6f75a00a..2d6de84a 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -162,7 +162,12 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId) if (!iarr.isNull()) { uint8_t oldSegId = strip.setPixelSegment(id); - //freeze and init to black + // set brightness immediately and disable transition + transitionDelayTemp = 0; + jsonTransitionOnce = true; + strip.setBrightness(scaledBri(bri), true); + + // freeze and init to black if (!seg.getOption(SEG_OPTION_FREEZE)) { seg.setOption(SEG_OPTION_FREEZE, true); strip.fill(0); @@ -250,7 +255,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) transitionDelayTemp *= 100; jsonTransitionOnce = true; } - strip.setTransition(transitionDelayTemp); + strip.setTransition(transitionDelayTemp); // required here for color transitions to have correct duration tr = root[F("tb")] | -1; if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis(); @@ -277,10 +282,16 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) realtimeOverride = root[F("lor")] | realtimeOverride; if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS; + bool liveEnabled = false; if (root.containsKey("live")) { bool lv = root["live"]; - if (lv) realtimeLock(65000); //enter realtime without timeout - else realtimeTimeout = 0; //cancel realtime mode immediately + if (lv) { + transitionDelayTemp = 0; + jsonTransitionOnce = true; + liveEnabled = true; // triggers realtimeLock() below + realtimeLock(65000); + } + else realtimeTimeout = 0; //cancel realtime mode immediately } strip.setMainSegmentId(root[F("mainseg")] | strip.getMainSegmentId()); @@ -358,6 +369,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) } stateUpdated(callMode); + if (liveEnabled) realtimeTimeout = UINT32_MAX; // force indefinite timeout if this request contained {"live":true} return stateResponse; } diff --git a/wled00/udp.cpp b/wled00/udp.cpp index e75a7f8f..35b14481 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -153,13 +153,13 @@ void realtimeLock(uint32_t timeoutMs, byte md) if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX; } // if strip is off (bri==0) and not already in RTM - if (bri == 0 && !realtimeMode) { - strip.setBrightness(scaledBri(briLast)); + if (briT == 0 && !realtimeMode) { + strip.setBrightness(scaledBri(briLast), true); } realtimeMode = md; - if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(scaledBri(255)); - if (md == REALTIME_MODE_GENERIC) strip.show(); + if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(scaledBri(255), true); + if (briT > 0 && md == REALTIME_MODE_GENERIC) strip.show(); } diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 10083318..4dafaa54 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -170,7 +170,6 @@ void handleSerial() if (!realtimeOverride) setRealtimePixel(pixel++, red, green, blue, 0); if (--count > 0) state = AdaState::Data_Red; else { - // if (!realtimeMode && bri == 0) strip.setBrightness(briLast); //realtimeLock() handles turning strip on/off realtimeLock(realtimeTimeoutMs, REALTIME_MODE_ADALIGHT); if (!realtimeOverride) strip.show();