diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 69a742c3d..331ceb077 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1216,11 +1216,11 @@ void WS2812FX::finalizeInit(void) { if (BusManager::getNumBusses() == 0) { DEBUG_PRINTLN(F("No busses, init default")); constexpr unsigned defDataTypes[] = {LED_TYPES}; - const unsigned defDataPins[] = {DATA_PINS}; - const unsigned defCounts[] = {PIXEL_COUNTS}; - const unsigned defNumTypes = ((sizeof defDataTypes) / (sizeof defDataTypes[0])); + constexpr unsigned defDataPins[] = {DATA_PINS}; + constexpr unsigned defCounts[] = {PIXEL_COUNTS}; + constexpr unsigned defNumTypes = ((sizeof defDataTypes) / (sizeof defDataTypes[0])); constexpr unsigned defNumPins = ((sizeof defDataPins) / (sizeof defDataPins[0])); - const unsigned defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0])); + constexpr unsigned defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0])); static_assert(Bus::getNumberOfPins(defDataTypes[0]) <= defNumPins, "The first LED type configured requires more pins than have been defined!"); @@ -1237,14 +1237,18 @@ void WS2812FX::finalizeInit(void) { DEBUG_PRINTLN(F("LED outputs misaligned with defined pins. Some pins will remain unused.")); break; } - for (unsigned j = 0; j < busPins && j < OUTPUT_MAX_PINS; j++) defPin[j] = defDataPins[pinsIndex + j]; - pinsIndex += busPins; - // when booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware - // i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), etc - if (pinManager.isPinAllocated(defPin[0])) { - defPin[0] = 1; // start with GPIO1 and work upwards - while (pinManager.isPinAllocated(defPin[0]) && defPin[0] < WLED_NUM_PINS) defPin[0]++; + for (unsigned j = 0; j < busPins && j < OUTPUT_MAX_PINS; j++) { + defPin[j] = defDataPins[pinsIndex + j]; + + // when booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware + // i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), read/only pins, etc. + if (pinManager.isPinAllocated(defPin[j]) || pinManager.isReadOnlyPin(defPin[j])) { + defPin[j] = 1; // start with GPIO1 and work upwards + while (pinManager.isPinAllocated(defPin[j]) && pinManager.isReadOnlyPin(defPin[j]) && defPin[j] < WLED_NUM_PINS) defPin[j]++; + } } + pinsIndex += busPins; + unsigned start = prevLen; // if we have less counts than pins and they do not align, use last known count to set current count unsigned count = defCounts[(i < defNumCounts) ? i : defNumCounts -1]; diff --git a/wled00/const.h b/wled00/const.h index cb50a108f..ffefb3ca5 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -572,6 +572,19 @@ #endif #endif +// List of read only pins. Cannot be used for LED outputs. +#if defined(CONFIG_IDF_TARGET_ESP32S2) + #define READ_ONLY_PINS 46 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) +// none for S3 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) +// none for C3 +#elif defined(ESP32) + #define READ_ONLY_PINS 34,35,36,37,38,39 +#else +// none for ESP8266 +#endif + #ifdef WLED_ENABLE_DMX #if (LEDPIN == 2) #undef LEDPIN diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 0a0f39155..507ce81cd 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -267,6 +267,29 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) const return false; } +unsigned *PinManagerClass::getReadOnlyPins() +{ + #ifdef READ_ONLY_PINS + static unsigned readOnlyPins[] = {READ_ONLY_PINS}; + #elif + static unsigned readOnlyPins[] = 255; + #endif + return readOnlyPins; +} + +bool PinManagerClass::isReadOnlyPin(byte gpio) +{ + const unsigned* pins = PinManagerClass::getReadOnlyPins(); + const unsigned numPins = sizeof(pins) / sizeof(pins[0]); + + for (unsigned i = 0; i < numPins; i++) { + if (pins[i] == gpio) { + return true; + } + } + return false; +} + PinOwner PinManagerClass::getPinOwner(byte gpio) const { if (!isPinOk(gpio, false)) return PinOwner::None; diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index 986964a7f..b441b89af 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -112,6 +112,9 @@ class PinManagerClass { // will return false for reserved pins bool isPinOk(byte gpio, bool output = true) const; + static unsigned* getReadOnlyPins(); + static bool isReadOnlyPin(byte gpio); + PinOwner getPinOwner(byte gpio) const; #ifdef ARDUINO_ARCH_ESP32 diff --git a/wled00/xml.cpp b/wled00/xml.cpp index c06b02768..8f8dd9e7d 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -191,17 +191,15 @@ void appendGPIOinfo() { // add info for read-only GPIO oappend(SET_F("d.ro_gpio=[")); - #if defined(CONFIG_IDF_TARGET_ESP32S2) - oappendi(46); - #elif defined(CONFIG_IDF_TARGET_ESP32S3) - // none for S3 - #elif defined(CONFIG_IDF_TARGET_ESP32C3) - // none for C3 - #elif defined(ESP32) - oappend(SET_F("34,35,36,37,38,39")); - #else - // none for ESP8266 - #endif + const unsigned* readOnlyPins = pinManager.getReadOnlyPins(); + const unsigned numReadOnlyPins = ((sizeof readOnlyPins) / (sizeof readOnlyPins[0])); + for (unsigned i = 0; i < numReadOnlyPins; i++) { + // Ignore 255 + if (readOnlyPins[i] <= WLED_NUM_PINS) { + oappendi(readOnlyPins[i]); + if (i != numReadOnlyPins) oappend(SET_F(",")); + } + } oappend(SET_F("];")); // add info about max. # of pins