Merge branch 'mdev' into dmx_input

This commit is contained in:
netmindz
2024-01-16 13:27:42 +00:00
committed by GitHub
130 changed files with 8433 additions and 6846 deletions

View File

@@ -3,6 +3,8 @@
#include "wled_ethernet.h"
#include <Arduino.h>
#warning WLED-MM GPL-v3. By installing WLED MM you implicitly accept the terms!
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
@@ -62,6 +64,22 @@
// WLEDMM end
#if INCLUDE_xTaskGetHandle && defined(ARDUINO_ARCH_ESP32) && (defined(WLED_DEBUG) || defined(WLED_DEBUG_HEAP))
// WLEDMM stack debug tool - find async_tcp task, and queries it's free stack
static int wledmm_get_tcp_stacksize(void) {
static TaskHandle_t tcp_taskHandle = NULL; // to store the task handle for later calls
char * tcp_taskname = pcTaskGetTaskName(tcp_taskHandle); // ask for name of the known task (to make sure we are still looking at the right one)
if ((tcp_taskHandle == NULL) || (tcp_taskname == NULL) || (strncmp(tcp_taskname, "async_tcp", 9) != 0)) {
tcp_taskHandle = xTaskGetHandle("async_tcp"); // need to look for the task by name. FreeRTOS docs say this is very slow, so we store the result for next time
//DEBUG_PRINT(F("async_tcp task ")); DEBUG_PRINTLN( (tcp_taskHandle != NULL) ? F("found") : F("not found"));
}
if (tcp_taskHandle != NULL) return uxTaskGetStackHighWaterMark(tcp_taskHandle); // got it !!
else return -1;
}
#endif
/*
* Main WLED class implementation. Mostly initialization and connection logic
*/
@@ -198,7 +216,7 @@ void WLED::loop()
#endif
if (!offMode || strip.isOffRefreshRequired()) {
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_PROTECT_SERVICE) // WLEDMM experimental
static unsigned long lastTimeService = 0; // WLEMM needed to remove stale lock
static unsigned long lastTimeService = 0; // WLEDMM needed to remove stale lock
if (!suspendStripService && !doInitBusses && !loadLedmap) { // WLEDMM prevent effect drawing while strip or segments are being updated
#endif
strip.service();
@@ -234,7 +252,7 @@ void WLED::loop()
if (lastMqttReconnectAttempt > millis()) {
rolloverMillis++;
lastMqttReconnectAttempt = 0;
ntpLastSyncTime = 0;
ntpLastSyncTime = NTP_NEVER; // force new NTP query
strip.restartRuntime();
}
if (millis() - lastMqttReconnectAttempt > 30000 || lastMqttReconnectAttempt == 0) { // lastMqttReconnectAttempt==0 forces immediate broadcast
@@ -349,6 +367,10 @@ void WLED::loop()
if (millis() - debugTime > 4999 ) { // WLEDMM: Special case for debugging heap faster
DEBUG_PRINT(F("*** Free heap: ")); DEBUG_PRINT(heap_caps_get_free_size(0x1800));
DEBUG_PRINT(F("\tLargest free block: ")); DEBUG_PRINT(heap_caps_get_largest_free_block(0x1800));
DEBUG_PRINT(F(" *** \t\tArduino min free stack: ")); DEBUG_PRINT(uxTaskGetStackHighWaterMark(NULL));
#if INCLUDE_xTaskGetHandle
DEBUG_PRINT(F(" TCP min free stack: ")); DEBUG_PRINT(wledmm_get_tcp_stacksize());
#endif
DEBUG_PRINTLN(F(" ***"));
debugTime = millis();
}
@@ -364,6 +386,23 @@ void WLED::loop()
ESP.wdtFeed();
#endif
#endif
#if 0 && defined(ALL_JSON_TO_PSRAM) && defined(WLED_USE_PSRAM_JSON)
// WLEDMM experiment - JSON garbagecollect once per minute. Warning: may crash at random
static unsigned long last_gc_time = 0;
// try once in 60 seconds
if ((millis() - last_gc_time) > 60000) {
// look for a perfect moment -> make sure no strip or segments or presets activity, no configs being updated, no realtime external control
if (!suspendStripService && !doInitBusses && !doReboot && !doCloseFile && !realtimeMode && !loadLedmap && !presetsActionPending()) {
// make sure JSON buffer is not in use
if ( (doSerializeConfig == false) && (jsonBufferLock == 0) && (fileDoc == nullptr)) {
USER_PRINTLN(F("JSON gabage collection (regular)."));
doc.garbageCollect(); // WLEDMM experimental - trigger garbage collection on JSON doc memory pool.
// this will make any pending reference to JSON objects _invalid_
last_gc_time = millis();
} } }
#endif
}
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH)
@@ -416,6 +455,10 @@ void WLED::setup()
if (!Serial) delay(2500); // WLEDMM allow CDC USB serial to initialise
#endif
#if ARDUINO_USB_CDC_ON_BOOT || ARDUINO_USB_MODE
#if ARDUINO_USB_CDC_ON_BOOT && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6))
// WLEDMM avoid "hung devices" when USB_CDC is enabled; see https://github.com/espressif/arduino-esp32/issues/9043
Serial.setTxTimeoutMs(0); // potential side-effect: incomplete debug output, with missing characters whenever TX buffer is full.
#endif
if (!Serial) delay(2500); // WLEDMM: always allow CDC USB serial to initialise
if (Serial) Serial.println("wait 1"); // waiting a bit longer ensures that a debug messages are shown in serial monitor
if (!Serial) delay(2500);
@@ -533,7 +576,7 @@ void WLED::setup()
#endif
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#ifdef ARDUINO_ARCH_ESP32
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) // unfortunately not availeable in older framework versions
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) // unfortunately not available in older framework versions
DEBUG_PRINT(F("\nArduino max stack ")); DEBUG_PRINTLN(getArduinoLoopTaskStackSize());
#endif
DEBUG_PRINTF("%s min free stack %d\n", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); //WLEDMM
@@ -547,12 +590,12 @@ void WLED::setup()
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
// S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
//managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} };
//pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
// C3: reserve GPIO 12-17 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation)
managed_pin_type pins[] = { {12, true}, {13, true}, {14, true}, {15, true}, {16, true}, {17, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
//managed_pin_type pins[] = { {12, true}, {13, true}, {14, true}, {15, true}, {16, true}, {17, true} };
//pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#else
// GPIO16/GPIO17 reserved for SPI RAM
managed_pin_type pins[] = { {16, true}, {17, true} };
@@ -566,11 +609,16 @@ void WLED::setup()
#else
DEBUG_PRINTLN(F("PSRAM not used."));
#endif
#endif
#if defined(ARDUINO_ESP32_PICO)
// special handling for PICO-D4: gpio16+17 are in use for onboard SPI FLASH (not PSRAM)
managed_pin_type pins[] = { {16, true}, {17, true} };
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
#endif
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
USER_FLUSH(); // WLEDMM flush buffer now, before anything time-critial is started.
USER_FLUSH(); // WLEDMM flush buffer now, before anything time-critical is started.
pinManager.manageDebugTXPin();
@@ -578,6 +626,11 @@ void WLED::setup()
pinManager.allocatePin(2, true, PinOwner::DMX);
#endif
#if defined(ALL_JSON_TO_PSRAM) && defined(WLED_USE_PSRAM_JSON)
USER_PRINTLN(F("JSON gabage collection (initial)."));
doc.garbageCollect(); // WLEDMM experimental - this seems to move the complete doc[] into PSRAM
#endif
// WLEDMM experimental: support for single neoPixel on Adafruit boards
#if 0
//#ifdef PIN_NEOPIXEL
@@ -607,7 +660,7 @@ void WLED::setup()
for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) btnPin[i] = -1;
bool fsinit = false;
USER_PRINTLN(F("Mount FS"));
USER_PRINTLN(F("Mounting FS ..."));
#ifdef ARDUINO_ARCH_ESP32
fsinit = WLED_FS.begin(true);
#else
@@ -616,6 +669,8 @@ void WLED::setup()
if (!fsinit) {
USER_PRINTLN(F("Mount FS failed!")); // WLEDMM
errorFlag = ERR_FS_BEGIN;
} else {
USER_PRINTLN(F("Mount FS succeeded.")); // WLEDMM
}
#ifdef WLED_ADD_EEPROM_SUPPORT
else deEEP();
@@ -715,7 +770,20 @@ void WLED::setup()
DEBUG_PRINT(pcTaskGetTaskName(NULL)); DEBUG_PRINT(F(" free stack ")); DEBUG_PRINTLN(uxTaskGetStackHighWaterMark(NULL));
#endif
// Seed FastLED random functions with an esp random value, which already works properly at this point.
#if defined(ARDUINO_ARCH_ESP32)
uint32_t seed32 = esp_random();
seed32 ^= random(0, INT32_MAX); // WLEDMM some extra entropy (for older frameworks where esp_ramdom alone might be too predictable after startup)
#elif defined(ARDUINO_ARCH_ESP8266)
const uint32_t seed32 = RANDOM_REG32;
#else
const uint32_t seed32 = random(std::numeric_limits<long>::max());
#endif
random16_set_seed((uint16_t)((seed32 & 0xFFFF) ^ (seed32 >> 16)));
#if WLED_WATCHDOG_TIMEOUT > 0
enableWatchdog();
#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
@@ -967,7 +1035,7 @@ void WLED::initConnection()
WiFi.disconnect(true); // close old connections
#ifdef ESP8266
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
#endif
if (staticIP[0] != 0 && staticGateway[0] != 0) {
@@ -1138,16 +1206,19 @@ void WLED::handleConnection()
#ifdef ARDUINO_ARCH_ESP32
// reconnect WiFi to clear stale allocations if heap gets too low
if (now - heapTime > 5000) { // WLEDMM: updated with better logic for small heap available by block, not total.
// uint32_t heap = ESP.getFreeHeap();
#if defined(ARDUINO_ARCH_ESP32S2)
uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2
#else
uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap.
#endif
if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) {
DEBUG_PRINT(F("Heap too low! (step 2, force reconnect): "));
DEBUG_PRINTLN(heap);
USER_PRINT(F("Heap too low! (step 2, force reconnect): "));
USER_PRINTLN(heap);
forceReconnect = true;
strip.purgeSegments(true); // remove all but one segments from memory
} else if (heap < MIN_HEAP_SIZE) {
DEBUG_PRINT(F("Heap too low! (step 1, flush unread UDP): "));
DEBUG_PRINTLN(heap);
USER_PRINT(F("Heap too low! (step 1, flush unread UDP): "));
USER_PRINTLN(heap);
strip.purgeSegments();
notifierUdp.flush();
rgbUdp.flush();
@@ -1275,7 +1346,15 @@ void WLED::handleStatusLED()
if (ledStatusType) {
if (millis() - ledStatusLastMillis >= (1000/ledStatusType)) {
ledStatusLastMillis = millis();
ledStatusState = !ledStatusState;
#if 0
// WLEDMM un-comment this to stop the blinking
if ((ledStatusType != 2) && (ledStatusType != 4))
ledStatusState = !ledStatusState;
else
ledStatusState = HIGH;
#else
ledStatusState = !ledStatusState;
#endif
#if STATUSLED>=0
digitalWrite(STATUSLED, ledStatusState);
#else