diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 74d612564..6f218c93f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -76,7 +76,7 @@ static constexpr unsigned sumPinsRequired(const unsigned* current, size_t count) static constexpr bool validatePinsAndTypes(const unsigned* types, unsigned numTypes, unsigned numPins ) { // Pins provided < pins required -> always invalid // Pins provided = pins required -> always valid - // Pins provided > pins required -> last type will repeat until we run out of pins, make sure excess pins modulo last type pins == 0 + // Pins provided > pins required -> valid if excess pins are a product of last type pins since it will be repeated return (sumPinsRequired(types, numTypes) > numPins) ? false : (numPins - sumPinsRequired(types, numTypes)) % Bus::getNumberOfPins(types[numTypes-1]) == 0; } @@ -1240,7 +1240,7 @@ void WS2812FX::finalizeInit(void) { unsigned prevLen = 0; unsigned pinsIndex = 0; for (unsigned i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) { - uint8_t defPin[OUTPUT_MAX_PINS]; // max 5 pins + uint8_t defPin[OUTPUT_MAX_PINS]; // if we have less types than requested outputs and they do not align, use last known type to set current type unsigned dataType = defDataTypes[(i < defNumTypes) ? i : defNumTypes -1]; unsigned busPins = Bus::getNumberOfPins(dataType); @@ -1259,8 +1259,19 @@ void WS2812FX::finalizeInit(void) { // 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 - // @FIX pins are allocated after the loop, so if we reassign to a pin that's already in the array for this output 2 fields will have the same pin - while ((pinManager.isPinAllocated(defPin[j]) || pinManager.isReadOnlyPin(defPin[j])) && defPin[j] < WLED_NUM_PINS) defPin[j]++; + while ( + ( + pinManager.isPinAllocated(defPin[j]) || + pinManager.isReadOnlyPin(defPin[j]) || + // Check if pin is defined for current bus + pinManager.isPinDefined(defPin[j], defDataPins, pinsIndex + j, pinsIndex + busPins) + ) + && + defPin[j] < WLED_NUM_PINS + ) + { + defPin[j]++; + } } } pinsIndex += busPins; diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 2bd82115f..814d81c1a 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -281,6 +281,13 @@ bool PinManagerClass::isReadOnlyPin(byte gpio) return false; } +bool PinManagerClass::isPinDefined(byte gpio, const unsigned *pins, unsigned start, unsigned end) { + for (unsigned i = start; i < end; 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 a8ddf5f75..1263dc4f4 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -113,6 +113,7 @@ class PinManagerClass { bool isPinOk(byte gpio, bool output = true) const; static bool isReadOnlyPin(byte gpio); + static bool isPinDefined(byte gpio, const unsigned* pins, unsigned start = 0, unsigned end = WLED_NUM_PINS); PinOwner getPinOwner(byte gpio) const;