diff --git a/platformio.ini b/platformio.ini index faa6f162a..6dd2ae5c4 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 +default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32s2_saola # Build everything ; default_envs = esp32dev, esp8285_4CH_MagicHome, esp8285_4CH_H801, 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_5CH_H801, d1_mini_debug, wemos_shield_esp32, elekstube_ips @@ -54,13 +54,14 @@ extra_configs = arduino_core_2_6_3 = espressif8266@2.3.3 arduino_core_2_7_4 = espressif8266@2.6.2 arduino_core_3_0_0 = espressif8266@3.0.0 +arduino_core_3_0_2 = espressif8266@3.2.0 # Development platforms arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage # Platform to use for ESP8266 -platform_wled_default = ${common.arduino_core_2_7_4} +platform_wled_default = ${common.arduino_core_3_0_2} # We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7 platformio/toolchain-xtensa @ ~2.40802.200502 @@ -105,6 +106,7 @@ build_flags = -DBEARSSL_SSL_BASIC -D CORE_DEBUG_LEVEL=0 -D NDEBUG + -Dregister= #build_flags for the IRremoteESP8266 library (enabled decoders have to appear here) -D _IR_ENABLE_DEFAULT_=false -D DECODE_HASH=true @@ -162,8 +164,7 @@ lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.4.0 IRremoteESP8266 @ 2.7.18 - https://github.com/lorol/LITTLEFS.git - https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.2 + https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.4 #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #TFT_eSPI #For use SSD1306 OLED display uncomment following @@ -185,6 +186,7 @@ build_flags = -DFP_IN_IROM ;-Wno-deprecated-declarations ;-Wno-register + -Wno-misleading-indentation ; NONOSDK22x_190703 = 2.2.2-dev(38a443e) -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 ; lwIP 2 - Higher Bandwidth no Features @@ -198,6 +200,7 @@ build_flags = lib_deps = ${env.lib_deps} + https://github.com/lorol/LITTLEFS.git # ESPAsyncTCP @ 1.2.0 ESPAsyncUDP makuna/NeoPixelBus @ 2.6.7 # 2.6.5/2.6.6 and newer do not compile on ESP core < 3.0.0 @@ -212,13 +215,13 @@ default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = ${env.lib_deps} + https://github.com/lorol/LITTLEFS.git makuna/NeoPixelBus @ 2.6.7 https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 [esp32s2] build_flags = -g -DARDUINO_ARCH_ESP32 - -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DARDUINO_ARCH_ESP32S2 -DCONFIG_IDF_TARGET_ESP32S2 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -314,14 +317,13 @@ lib_deps = ${esp32.lib_deps} board_build.partitions = ${esp32.default_partitions} [env:esp32s2_saola] -board = esp32dev -board_build.mcu = esp32s2 -platform = espressif32 +board = esp32-s2-saola-1 +platform = https://github.com/tasmota/platform-espressif32/releases/download/v3.4.1/Tasmota-platform-espressif32.zip platform_packages = - toolchain-xtensa32s2 - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2.0.0-alpha1 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2.0.2 framework = arduino board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv +board_build.flash_mode = qio upload_speed = 460800 build_unflags = ${common.build_unflags} lib_deps = ${esp32s2.lib_deps} diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h index 3bf9fdd3a..35ea0d7a4 100644 --- a/usermods/Animated_Staircase/Animated_Staircase.h +++ b/usermods/Animated_Staircase/Animated_Staircase.h @@ -111,17 +111,17 @@ class Animated_Staircase : public Usermod { } if (i >= onIndex && i < offIndex) { - segments->setOption(SEG_OPTION_ON, 1, 1); + segments->setOption(SEG_OPTION_ON, 1, i); // We may need to copy mode and colors from segment 0 to make sure // changes are propagated even when the config is changed during a wipe // segments->mode = mainsegment.mode; // segments->colors[0] = mainsegment.colors[0]; } else { - segments->setOption(SEG_OPTION_ON, 0, 1); + segments->setOption(SEG_OPTION_ON, 0, i); } // Always mark segments as "transitional", we are animating the staircase - segments->setOption(SEG_OPTION_TRANSITIONAL, 1, 1); + segments->setOption(SEG_OPTION_TRANSITIONAL, 1, i); } colorUpdated(CALL_MODE_DIRECT_CHANGE); } @@ -296,7 +296,7 @@ class Animated_Staircase : public Usermod { maxSegmentId = i - 1; break; } - segments->setOption(SEG_OPTION_ON, 1, 1); + segments->setOption(SEG_OPTION_ON, 1, i); } colorUpdated(CALL_MODE_DIRECT_CHANGE); DEBUG_PRINTLN(F("Animated Staircase disabled.")); diff --git a/usermods/quinled-an-penta/quinled-an-penta.h b/usermods/quinled-an-penta/quinled-an-penta.h index 10777e36c..5153ee58a 100644 --- a/usermods/quinled-an-penta/quinled-an-penta.h +++ b/usermods/quinled-an-penta/quinled-an-penta.h @@ -61,10 +61,10 @@ class QuinLEDAnPentaUsermod : public Usermod float shtLastKnownHumidity = 0; // Pin/IO vars - const int8_t anPentaPins[5] = {14, 13, 12, 4, 2}; + const int8_t anPentaLEDPins[5] = {14, 13, 12, 4, 2}; int8_t oledSpiClk = 15; int8_t oledSpiData = 16; - int8_t oledSpiCs = 0; + int8_t oledSpiCs = 27; int8_t oledSpiDc = 32; int8_t oledSpiRst = 33; int8_t shtSda = 1; @@ -75,7 +75,7 @@ class QuinLEDAnPentaUsermod : public Usermod { for(int8_t i = 0; i <= 4; i++) { - if(anPentaPins[i] == pin) + if(anPentaLEDPins[i] == pin) return true; } return false; @@ -313,7 +313,7 @@ class QuinLEDAnPentaUsermod : public Usermod byte drawnLines = 0; for (int8_t app = 0; app <= 4; app++) { for (int8_t clp = 0; clp <= 4; clp++) { - if (anPentaPins[app] == currentLedPins[clp]) { + if (anPentaLEDPins[app] == currentLedPins[clp]) { char charCurrentLedcReads[17]; sprintf(charCurrentLedcReads, "LED %d:", app+1); if (oledUseProgressBars) { diff --git a/usermods/quinled-an-penta/readme.md b/usermods/quinled-an-penta/readme.md index c292736c8..4a4c0290a 100644 --- a/usermods/quinled-an-penta/readme.md +++ b/usermods/quinled-an-penta/readme.md @@ -1,12 +1,12 @@ # QuinLED-An-Penta -The (un)official usermod to get the best out of the QuinLED-An-Penta, like using the OLED and the SHT30 temperature/humidity sensor. +The (un)official usermod to get the best out of the QuinLED-An-Penta (https://quinled.info/quinled-an-penta/), like using the OLED and the SHT30 temperature/humidity sensor. ## Requirements * "u8gs" by olikraus, v2.28 or higher: https://github.com/olikraus/u8g2 * "SHT85" by Rob Tillaart, v0.2 or higher: https://github.com/RobTillaart/SHT85 ## Usermod installation -Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one and add the buildflag `-D QUINLED_AN_PENTA`. +Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one, add the buildflag `-D QUINLED_AN_PENTA` and the below library dependencies. ESP32 (**without** ethernet): ``` @@ -33,14 +33,19 @@ This mod has been optimized for an SSD1306 driven 128x64 OLED. Using a smaller O I highly recommend using these "two color monochromatic OLEDs", which have the first 16 pixels in a different color than the other 48, e.g. a yellow/blue OLED. Also note, you need to have an **SPI** driven OLED, **not i2c**! +### Limitations combined with Ethernet +The initial development of this mod had been done with a beta version of the QuinLED-An-Penta, which had a different IO layout for the OLED: The CS pin used to be IO_0, but has been changed to IO27 with the first v1 public release. Unfortunately, IO27 is used by the Ethernet boards, so WLED will not let you enable the OLED screen, if you're using it with Ethernet. This unfortunately makes the development I've done to support/show Ethernet information void, as it cannot be used. +However (and I've not tried this, as I don't own a v1 board): You can try to modify this mod and try to use IO27 for the OLED and share it with the Ethernet board. It is "just" the chip select pin, so there is a chance that both can coexist and use the same IO. You need to skip WLEDs PinManager for the CS pin, so WLED will not block using it. If you don't know how this works: Leave it. If you know what I'm talking about: Try it and please let me know on the Intermit.Tech (QuinLED) Discord server: https://discord.gg/WdbAauG + ### My OLED flickers after some time, what should I do? -That's a tricky one: During development I saw that the OLED sometimes starts to "bug out" / flicker and won't work anymore. This seems to be caused by the high PWM interference the board produces. It seems to loose it's settings and then doesn't know how to draw anymore. Turns out the only way to fix this is to call the libraries `begin()` method again which will re-initialize the display. +That's a tricky one: During development I saw that the OLED sometimes starts to "bug out" / flicker and won't work anymore. This seems to be caused by the high PWM interference the board produces. It seems to loose its settings and then doesn't know how to draw anymore. Turns out the only way to fix this is to call the libraries `begin()` method again which will re-initialize the display. If you're facing this issue, you can enable a setting I've added which will call the `begin()` roughly every 60 seconds between a page change. This will make the page change take ~500ms, but will fix the display. + ## Configuration Navigate to the "Config" and then to the "Usermods" section. If you compiled WLED with `-D QUINLED_AN_PENTA`, you will see the config for it there: * Enable-OLED: - * What it does: Enabled the optional SPI driven OLED that can be mounted to the 7-pin female header + * What it does: Enables the optional SPI driven OLED that can be mounted to the 7-pin female header. Won't work with Ethernet, read above. * Possible values: Enabled/Disabled * Default: Disabled * OLED-Use-Progress-Bars: @@ -60,10 +65,15 @@ Navigate to the "Config" and then to the "Usermods" section. If you compiled WLE * Possible values: Enabled/Disabled * Default: Disabled * Enable-SHT30-Temp-Humidity-Sensor: - * What it does: Enabled the onboard SHT30 temperature and humidity sensor + * What it does: Enables the onboard SHT30 temperature and humidity sensor * Possible values: Enabled/Disabled * Default: Disabled ## Change log +2021-12 +* Adjusted IO layout to match An-Penta v1r1 2021-10 -* First implementation. \ No newline at end of file +* First implementation. + +## Credits +ezcGman | Andy: Find me on the Intermit.Tech (QuinLED) Discord server: https://discord.gg/WdbAauG \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h index c4a648868..7b89c8d7d 100644 --- a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h +++ b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h @@ -65,7 +65,8 @@ private: { 1, 0, 1, 1, 1, 1, 1 }, // 6 { 1, 1, 1, 0, 0, 0, 0 }, // 7 { 1, 1, 1, 1, 1, 1, 1 }, // 8 - { 1, 1, 1, 1, 0, 1, 1 } // 9 + { 1, 1, 1, 1, 0, 1, 1 }, // 9 + { 0, 0, 0, 0, 0, 0, 0 } // blank }; //String to reduce flash memory usage @@ -100,39 +101,39 @@ private: switch (umSSDRDisplayMask[index]) { case 'h': timeVar = hourFormat12(localTime); - _showElements(&umSSDRHours, timeVar, 0); + _showElements(&umSSDRHours, timeVar, 0, 1); break; case 'H': timeVar = hour(localTime); - _showElements(&umSSDRHours, timeVar, 0); + _showElements(&umSSDRHours, timeVar, 0, 1); break; case 'k': timeVar = hour(localTime) + 1; - _showElements(&umSSDRHours, timeVar, 0); + _showElements(&umSSDRHours, timeVar, 0, 0); break; case 'm': timeVar = minute(localTime); - _showElements(&umSSDRMinutes, timeVar, 0); + _showElements(&umSSDRMinutes, timeVar, 0, 0); break; case 's': timeVar = second(localTime); - _showElements(&umSSDRSeconds, timeVar, 0); + _showElements(&umSSDRSeconds, timeVar, 0, 0); break; case 'd': timeVar = day(localTime); - _showElements(&umSSDRDays, timeVar, 0); + _showElements(&umSSDRDays, timeVar, 0, 0); break; case 'M': timeVar = month(localTime); - _showElements(&umSSDRMonths, timeVar, 0); + _showElements(&umSSDRMonths, timeVar, 0, 0); break; case 'y': timeVar = second(localTime); - _showElements(&umSSDRYears, timeVar, 0); + _showElements(&umSSDRYears, timeVar, 0, 0); break; case 'Y': timeVar = year(localTime); - _showElements(&umSSDRYears, timeVar, 0); + _showElements(&umSSDRYears, timeVar, 0, 0); break; case ':': if (!colonsDone) { // only call _setColons once as all colons are printed when the first colon is found @@ -148,14 +149,16 @@ private: void _setColons() { if ( umSSDRColonblink ) { if ( second(localTime) % 2 == 0 ) { - _showElements(&umSSDRColons, 0, 1); + _showElements(&umSSDRColons, 0, 1, 0); } } else { - _showElements(&umSSDRColons, 0, 1); + _showElements(&umSSDRColons, 0, 1, 0); } } - void _showElements(String *map, int timevar, bool isColon) { + void _showElements(String *map, int timevar, bool isColon, bool removeZero + +) { if (!(*map).equals("") && !(*map) == NULL) { int length = String(timevar).length(); bool addZero = false; @@ -165,8 +168,16 @@ private: } int timeArr[length]; if(addZero) { - timeArr[1] = 0; - timeArr[0] = timevar; + if(removeZero) + { + timeArr[1] = 10; + timeArr[0] = timevar; + } + else + { + timeArr[1] = 0; + timeArr[0] = timevar; + } } else { int count = 0; while (timevar) { diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cf46bf28c..9f7568028 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2091,7 +2091,7 @@ uint16_t WS2812FX::mode_colortwinkle() } } } - return FRAMETIME; + return FRAMETIME_FIXED; } @@ -2876,7 +2876,7 @@ uint16_t WS2812FX::candle(bool multi) } } - return FRAMETIME; + return FRAMETIME_FIXED; } uint16_t WS2812FX::mode_candle() diff --git a/wled00/FX.h b/wled00/FX.h index 7215e347b..afdf0103c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -48,7 +48,8 @@ /* Not used in all effects yet */ #define WLED_FPS 42 -#define FRAMETIME (1000/WLED_FPS) +#define FRAMETIME_FIXED (1000/WLED_FPS) +#define FRAMETIME _frametime /* each segment uses 52 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ @@ -71,7 +72,7 @@ #define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / MAX_NUM_SEGMENTS) #define LED_SKIP_AMOUNT 1 -#define MIN_SHOW_DELAY 15 +#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] @@ -648,12 +649,14 @@ class WS2812FX { calcGammaTable(float), trigger(void), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX), + restartRuntime(), resetSegments(), makeAutoSegments(), fixInvalidSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), show(void), + setTargetFps(uint8_t fps), setPixelSegment(uint8_t n), deserializeMap(uint8_t n=0); @@ -684,6 +687,7 @@ class WS2812FX { getActiveSegmentsNum(void), //getFirstSelectedSegment(void), getMainSegmentId(void), + getTargetFps(void), gamma8(uint8_t), gamma8_cal(uint8_t, float), sin_gap(uint16_t), @@ -855,6 +859,8 @@ class WS2812FX { uint16_t _usedSegmentData = 0; uint16_t _transitionDur = 750; + uint8_t _targetFps = 42; + uint16_t _frametime = (1000/42); uint16_t _cumulativeFps = 2; bool diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e8aaba267..c7ee98f86 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -165,12 +165,12 @@ void WS2812FX::service() { _triggered = false; } -void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { +void IRAM_ATTR WS2812FX::setPixelColor(uint16_t n, uint32_t c) { setPixelColor(n, R(c), G(c), B(c), W(c)); } //used to map from segment index to physical pixel, taking into account grouping, offsets, reverse and mirroring -uint16_t WS2812FX::realPixelIndex(uint16_t i) { +uint16_t IRAM_ATTR WS2812FX::realPixelIndex(uint16_t i) { int16_t iGroup = i * SEGMENT.groupLength(); /* reverse just an individual segment */ @@ -187,7 +187,7 @@ uint16_t WS2812FX::realPixelIndex(uint16_t i) { return realIndex; } -void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) +void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) { if (SEGLEN) {//from segment uint16_t realIndex = realPixelIndex(i); @@ -350,6 +350,15 @@ uint16_t WS2812FX::getFps() { return _cumulativeFps +1; } +uint8_t WS2812FX::getTargetFps() { + return _targetFps; +} + +void WS2812FX::setTargetFps(uint8_t fps) { + if (fps > 0 && fps <= 120) _targetFps = fps; + _frametime = 1000 / _targetFps; +} + /** * Forces the next frame to be computed on all active segments. */ @@ -606,6 +615,12 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, _segment_runtimes[n].reset(); } +void WS2812FX::restartRuntime() { + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { + _segment_runtimes[i].reset(); + } +} + void WS2812FX::resetSegments() { for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete[] _segments[i].name; mainSegment = 0; @@ -769,7 +784,7 @@ void WS2812FX::setTransitionMode(bool t) /* * color blend function */ -uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) { +uint32_t IRAM_ATTR WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) { if(blend == 0) return color1; uint16_t blendmax = b16 ? 0xFFFF : 0xFF; if(blend == blendmax) return color2; @@ -872,13 +887,13 @@ void WS2812FX::blur(uint8_t blur_amount) } } -uint16_t WS2812FX::triwave16(uint16_t in) +uint16_t IRAM_ATTR WS2812FX::triwave16(uint16_t in) { if (in < 0x8000) return in *2; return 0xFFFF - (in - 0x8000)*2; } -uint8_t WS2812FX::sin_gap(uint16_t in) { +uint8_t IRAM_ATTR WS2812FX::sin_gap(uint16_t in) { if (in & 0x100) return 0; //if (in > 255) return 0; return sin8(in + 192); //correct phase shift of sine so that it starts and stops at 0 @@ -945,13 +960,13 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) { } -uint32_t WS2812FX::crgb_to_col(CRGB fastled) +uint32_t IRAM_ATTR WS2812FX::crgb_to_col(CRGB fastled) { return RGBW32(fastled.red, fastled.green, fastled.blue, 0); } -CRGB WS2812FX::col_to_crgb(uint32_t color) +CRGB IRAM_ATTR WS2812FX::col_to_crgb(uint32_t color) { CRGB fastled_col; fastled_col.red = R(color); @@ -1074,7 +1089,7 @@ void WS2812FX::handle_palette(void) * @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling) * @returns Single color from palette */ -uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) +uint32_t IRAM_ATTR WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) { if (SEGMENT.palette == 0 && mcol < 3) { uint32_t color = SEGCOLOR(mcol); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index ab3156ff4..721183832 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -288,7 +288,7 @@ class BusPwm : public Bus { if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) { deallocatePins(); return; } - _pins[i] = currentPin; // store only after allocatePin() succeeds + _pins[i] = currentPin; //store only after allocatePin() succeeds #ifdef ESP8266 pinMode(_pins[i], OUTPUT); #else @@ -397,7 +397,7 @@ class BusPwm : public Bus { private: uint8_t _pins[5] = {255, 255, 255, 255, 255}; - uint8_t _data[5] = {255, 255, 255, 255, 255}; + uint8_t _data[5] = {0}; #ifdef ARDUINO_ARCH_ESP32 uint8_t _ledcStart = 255; #endif diff --git a/wled00/button.cpp b/wled00/button.cpp index 96cdfed5a..8bf1b4b06 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -210,6 +210,7 @@ void handleAnalog(uint8_t b) void handleButton() { static unsigned long lastRead = 0UL; + bool analog = false; for (uint8_t b=0; b 250) { // button is not a button but a potentiometer - if (b+1 == WLED_MAX_BUTTONS) lastRead = millis(); + analog = true; handleAnalog(b); continue; } @@ -275,6 +276,7 @@ void handleButton() shortPressAction(b); } } + if (analog) lastRead = millis(); } void handleIO() diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index f89dae836..f16c69263 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -85,6 +85,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(cctFromRgb, hw_led[F("cr")]); CJSON(strip.cctBlending, hw_led[F("cb")]); Bus::setCCTBlend(strip.cctBlending); + strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS JsonArray ins = hw_led["ins"]; @@ -366,7 +367,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(timerMinutes[it], timer["min"]); CJSON(timerMacro[it], timer["macro"]); - byte dowPrev = timerWeekday[it]; + byte dowPrev = timerWeekday[it]; //note: act is currently only 0 or 1. //the reason we are not using bool is that the on-disk type in 0.11.0 was already int int actPrev = timerWeekday[it] & 0x01; @@ -376,7 +377,17 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { int act = timer["en"] | actPrev; if (act) timerWeekday[it]++; } - + if (it<8) { + JsonObject start = timer["start"]; + byte startm = start["mon"]; + if (startm) timerMonth[it] = (startm << 4); + CJSON(timerDay[it], start["day"]); + JsonObject end = timer["end"]; + CJSON(timerDayEnd[it], end["day"]); + byte endm = end["mon"]; + if (startm) timerMonth[it] += endm & 0x0F; + if (!(timerMonth[it] & 0x0F)) timerMonth[it] += 12; //default end month to 12 + } it++; } @@ -540,6 +551,7 @@ void serializeConfig() { hw_led["cct"] = correctWB; hw_led[F("cr")] = cctFromRgb; hw_led[F("cb")] = strip.cctBlending; + hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); JsonArray hw_led_ins = hw_led.createNestedArray("ins"); @@ -742,6 +754,14 @@ void serializeConfig() { timers_ins0["min"] = timerMinutes[i]; timers_ins0["macro"] = timerMacro[i]; timers_ins0[F("dow")] = timerWeekday[i] >> 1; + if (i<8) { + JsonObject start = timers_ins0.createNestedObject("start"); + start["mon"] = (timerMonth[i] >> 4) & 0xF; + start["day"] = timerDay[i]; + JsonObject end = timers_ins0.createNestedObject("end"); + end["mon"] = timerMonth[i] & 0xF; + end["day"] = timerDayEnd[i]; + } } JsonObject ota = doc.createNestedObject("ota"); diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 86cdb510d..8dd81e446 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -571,6 +571,7 @@ ${i+1}:
+ Target refresh rate: FPS
Config template:

diff --git a/wled00/data/settings_time.htm b/wled00/data/settings_time.htm index 622cff668..29cf0968f 100644 --- a/wled00/data/settings_time.htm +++ b/wled00/data/settings_time.htm @@ -6,9 +6,11 @@ Time Settings