diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 8194659d..c8d8a7b4 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -12,6 +12,7 @@ static void DebugPrintOwnerTag(PinOwner tag) { uint32_t q = static_cast(tag); if (q) { + DEBUG_PRINT(pinManager.getOwnerText(tag)); DEBUG_PRINT(F(" = ")); // WLEDMM DEBUG_PRINTF("0x%02x (%d)", q, q); } else { DEBUG_PRINT(F("(no owner)")); @@ -26,8 +27,11 @@ String PinManagerClass::getPinOwnerText(int gpio) { //if (gpio >= GPIO_PIN_COUNT) return(F("n/a")); if (!isPinOk(gpio, false)) return(F("n/a")); if (!isPinAllocated(gpio)) return(F("./.")); + return(getOwnerText(getPinOwner(gpio))); +} - switch(getPinOwner(gpio)) { +String PinManagerClass::getOwnerText(PinOwner tag) { + switch(tag) { case PinOwner::None : return(F("no owner")); break; // unknown - no owner case PinOwner::DebugOut : return(F("debug output")); break; // 'Dbg' == debug output always IO1 case PinOwner::Ethernet : return(F("Ethernet")); break; // Ethernet @@ -62,7 +66,7 @@ String PinManagerClass::getPinOwnerText(int gpio) { } String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN info - if ((gpio == 0xFF) || (gpio < 0)) return(F("")); // explicitly allow clients to free -1 as a no-op + if ((gpio == 0xFF) || (gpio < 0)) return(F("")); // explicitly allow -1 as a no-op // audioreactive settings - unfortunately, these are hiddden inside usermod now :-( // if((gpio == audioPin) && (dmType == 0)) return(F("analog audio in")); @@ -182,6 +186,16 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in return(F("")); // default - nothing special to say } +String PinManagerClass::getPinConflicts(int gpio) { + if ((gpio == 0xFF) || (gpio < 0)) return(F("")); // explicitly allow -1 as a no-op + if (!isPinOk(gpio, false)) return(F("")); // invalid GPIO + + if (ownerConflict[gpio] == PinOwner::None) { + return(F("")); // no conflict fot this GPIO + } else { // found previous conflic! + return String("!! Conflict with ") + getOwnerText(ownerConflict[gpio]) + String(" !!"); + } +} // WLEDMM end /// Actual allocation/deallocation routines @@ -196,7 +210,6 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) DEBUG_PRINT(F("PIN DEALLOC: IO ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(ownerTag[gpio]); DEBUG_PRINT(F(", but attempted de-allocation by ")); DebugPrintOwnerTag(tag); @@ -208,6 +221,7 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) byte bi = gpio - 8*by; bitWrite(pinAlloc[by], bi, false); ownerTag[gpio] = PinOwner::None; + // ownerConflict[gpio] = PinOwner::None; // WLEDMM clear conflict (if any) return true; } @@ -232,7 +246,6 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array DEBUG_PRINT(F("PIN DEALLOC: IO ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(ownerTag[gpio]); DEBUG_PRINT(F(", but attempted de-allocation by ")); DebugPrintOwnerTag(tag); @@ -280,8 +293,9 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by } if (!isPinOk(gpio, mptArray[i].isOutput)) { #ifdef WLED_DEBUG - DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: ")); + DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: GPIO ")); DEBUG_PRINT(gpio); + DEBUG_PRINT(" as "); DEBUG_PRINT(mptArray[i].isOutput ? "output": "input"); // WLEDMM DEBUG_PRINTLN(F("")); #endif shouldFail = true; @@ -290,11 +304,11 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by // allow multiple "allocations" of HW I2C & SPI bus pins continue; } else if (isPinAllocated(gpio)) { + ownerConflict[gpio] = tag; // WLEDMM record conflict #ifdef WLED_DEBUG DEBUG_PRINT(F("PIN ALLOC: FAIL: IO ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" already allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(ownerTag[gpio]); DEBUG_PRINTLN(F("")); #endif @@ -320,11 +334,11 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by byte bi = gpio - 8*by; bitWrite(pinAlloc[by], bi, true); ownerTag[gpio] = tag; + // ownerConflict[gpio] = PinOwner::None; // WLEDMM clear conflict (if any) #ifdef WLED_DEBUG DEBUG_PRINT(F("PIN ALLOC: Pin ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(tag); DEBUG_PRINTLN(F("")); #endif @@ -353,11 +367,11 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) return false; } if (isPinAllocated(gpio)) { + ownerConflict[gpio] = tag; // WLEDMM record conflict #ifdef WLED_DEBUG DEBUG_PRINT(F("PIN ALLOC: Pin ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" already allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(ownerTag[gpio]); DEBUG_PRINTLN(F("")); #endif @@ -368,11 +382,11 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) byte bi = gpio - 8*by; bitWrite(pinAlloc[by], bi, true); ownerTag[gpio] = tag; + // ownerConflict[gpio] = PinOwner::None; // WLEDMM clear conflict (if any) #ifdef WLED_DEBUG DEBUG_PRINT(F("PIN ALLOC: Pin ")); DEBUG_PRINT(gpio); DEBUG_PRINT(F(" successfully allocated by ")); - DEBUG_PRINT(getPinOwnerText(gpio)); DEBUG_PRINT(F(" = ")); // WLEDMM DebugPrintOwnerTag(tag); DEBUG_PRINTLN(F("")); #endif @@ -383,9 +397,17 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) // if tag is set to PinOwner::None, checks for ANY owner of the pin. // if tag is set to any other value, checks if that tag is the current owner of the pin. bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) -{ +{ if (!isPinOk(gpio, false)) return true; - if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false; + if (gpio == 0xFF) { + DEBUG_PRINT(F(" isPinAllocated: -1 is never allocacted! ")); + return false; // WLEDMM bugfix - avoid invalid index to array + } + + if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) { + if ((ownerTag[gpio] != PinOwner::None) && (tag != PinOwner::HW_I2C) && (tag != PinOwner::HW_SPI)) ownerConflict[gpio] = tag; // WLEDMM record conflict + return false; + } byte by = gpio >> 3; byte bi = gpio - (by<<3); return bitRead(pinAlloc[by], bi); diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index 3d99076b..3184b42f 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -67,10 +67,12 @@ class PinManagerClass { #ifdef ESP8266 uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits PinOwner ownerTag[17] = { PinOwner::None }; + PinOwner ownerConflict[17] = { PinOwner::None }; // WLEDMM: record pin alloc conflicts #else uint8_t pinAlloc[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //WLEDMM bugfix - 56bit, 1 bit per pin, we use 50 bits on -S3 uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels PinOwner ownerTag[50] = { PinOwner::None }; // WLEDMM bugfix - new MCU's have up to 50 GPIO + PinOwner ownerConflict[50] = { PinOwner::None }; // WLEDMM: record pin alloc conflicts #endif struct { uint8_t i2cAllocCount : 4; // allow multiple allocation of I2C bus pins but keep track of allocations @@ -108,9 +110,10 @@ class PinManagerClass { bool isPinOk(byte gpio, bool output = true); PinOwner getPinOwner(byte gpio); - //String getOwnerText(PinOwner tag); // WLEDMM work in progress - String getPinOwnerText(int gpio); // WLEDMM - String getPinSpecialText(int gpio); // WLEDMM + String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text + String getPinOwnerText(int gpio); // WLEDMM - return PIN owner as text + String getPinSpecialText(int gpio); // WLEDMM - return PIN special comments (if any) + String getPinConflicts(int gpio); // WLEDMM - return PIN alloc conflicts (if any) #ifdef ARDUINO_ARCH_ESP32 byte allocateLedc(byte channels); void deallocateLedc(byte pos, byte channels); diff --git a/wled00/set.cpp b/wled00/set.cpp index 8caad36c..8d44efec 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -169,7 +169,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) btnPin[i] = hw_btn_pin; buttonType[i] = request->arg(be).toInt(); #ifdef ESP32 - pinMode(btnPin[i], buttonType[i]==BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP); + if (((buttonType[i] == BTN_TYPE_ANALOG) || (buttonType[i] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[i]) < 0)) { // WLEDMM + // not an ADC analog pin + DEBUG_PRINTF("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n", btnPin[i], i); + btnPin[i] = -1; + pinManager.deallocatePin(hw_btn_pin,PinOwner::Button); + } else { // WLEDMM end + pinMode(btnPin[i], buttonType[i]==BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP); + } #else pinMode(btnPin[i], INPUT_PULLUP); #endif diff --git a/wled00/wled.cpp b/wled00/wled.cpp index b78827cc..e756da57 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -480,10 +480,11 @@ void WLED::setup() if(pinManager.isPinOk(pinNr, false)) { if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // comment out to include no-name,unused GPIO pins bool is_inOut = pinManager.isPinOk(pinNr, true); - Serial.printf("%s %2d\t %-18s\t %s\n", + Serial.printf("%s %2d\t %-17s %s\t %s\n", (is_inOut?"i/o":"in "), pinNr, - pinManager.getPinOwnerText(pinNr).c_str(), + pinManager.getPinOwnerText(pinNr).c_str(), + pinManager.getPinConflicts(pinNr).c_str(), pinManager.getPinSpecialText(pinNr).c_str() ); } diff --git a/wled00/wled.h b/wled00/wled.h index e3491c84..196d4e98 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2211291 +#define VERSION 2212041 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG