From 0dfc884c644ea29380a0ea4e1046bbff1055030c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 2 Dec 2022 00:11:28 +0100 Subject: [PATCH] very medium updates (GPIO info, part1) Improvements for debugging GPIO conflicts. HTML UI integration still pending. * pinManager can be asked for pin owner (String) and pin special purpose (string). * wled.cpp: show GPIO allocation when compiling with WLED_DEBUG * pinmanager: show Pin Owner as name when possible. The results looks like this GPIO | Assigned to | Info --------|-----------------------|------------ i/o 0 Button i/o 1 debug Serial TX i/o 2 DMX out i/o 3 ./. Serial RX i/o 5 ./. SPI SS i/o 15 AudioReactive (UM) i/o 16 LEDs (digital) i/o 17 Relay i/o 18 ./. SPI CLK i/o 19 IR Receiver SPI MISO i/o 21 I2C I2C SDA i/o 22 I2C I2C SCL i/o 23 ./. SPI MOSI i/o 32 AudioReactive (UM) --- wled00/pin_manager.cpp | 105 +++++++++++++++++++++++++++++++++++++++++ wled00/pin_manager.h | 3 +- wled00/wled.cpp | 21 +++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index fb1d3a99..bd072aa8 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -1,6 +1,12 @@ #include "pin_manager.h" #include "wled.h" +#ifdef ARDUINO_ARCH_ESP32 +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) +#include // WLEDMM +#endif +#endif + #ifdef WLED_DEBUG static void DebugPrintOwnerTag(PinOwner tag) { @@ -13,6 +19,99 @@ static void DebugPrintOwnerTag(PinOwner tag) } #endif +// WLEDMM begin + +String PinManagerClass::getPinOwnerText(int gpio) { + if ((gpio < 0) || (gpio == 0xFF)) return(F("")); + //if (gpio >= GPIO_PIN_COUNT) return(F("n/a")); + if (!isPinOk(gpio, false)) return(F("n/a")); + if (!isPinAllocated(gpio)) return(F("./.")); + + switch(getPinOwner(gpio)) { + case PinOwner::None : return(F("availeable")); break; // no owner + case PinOwner::DebugOut : return(F("debug")); break; // 'Dbg' == debug output always IO1 + case PinOwner::Ethernet : return(F("Ethernet")); break; // Ethernet + case PinOwner::BusDigital : return(F("LEDs (digital)")); break; // Digital LEDs + case PinOwner::BusPwm : return(F("LEDs (PWM)")); break; // PWM output using BusPwm + case PinOwner::BusOnOff : return(F("LEDs (on-off)")); break; // + case PinOwner::Button : return(F("Button")); break; // 'Butn' == button from configuration + case PinOwner::IR : return(F("IR Receiver")); break; // 'IR' == IR receiver pin from configuration + case PinOwner::Relay : return(F("Relay")); break; // 'Rly' == Relay pin from configuration + case PinOwner::SPI_RAM : return(F("PSRAM")); break; // 'SpiR' == SPI RAM (aka PSRAM) + case PinOwner::DMX : return(F("DMX out")); break; // 'DMX' == hard-coded to IO2 + case PinOwner::HW_I2C : return(F("I2C")); break; // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32) + case PinOwner::HW_SPI : return(F("SPI")); break; // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32) + + case PinOwner::UM_Audioreactive : return(F("AudioReactive (UM)")); break; // audioreative usermod - analog or digital audio input + case PinOwner::UM_Temperature : return(F("Temperature (UM)")); break; // "usermod_temperature.h" + case PinOwner::UM_PIR : return(F("PIR (UM)")); break; // "usermod_PIR_sensor_switch.h" + case PinOwner::UM_FourLineDisplay : return(F("4Line Display (UM)")); break; // "usermod_v2_four_line_display.h -- May use "standard" HW_I2C pins + case PinOwner::UM_RotaryEncoderUI : return(F("Rotary Enc. (UM)")); break; // "usermod_v2_rotary_encoder_ui.h" + case PinOwner::UM_MultiRelay : return(F("Multi Relay (UM)")); break; // "usermod_multi_relay.h" + case PinOwner::UM_AnimatedStaircase : return(F("AnimatedStaircase (UM)")); break; // "Animated_Staircase.h" + case PinOwner::UM_RGBRotaryEncoder : return(F("RGB Rotary Enc. (UM)")); break; // "rgb-rotary-encoder.h" + case PinOwner::UM_QuinLEDAnPenta : return(F("QuinLEDAnPenta (UM)")); break; // "quinled-an-penta.h" + case PinOwner::UM_BME280 : return(F("BME280 (UM)")); break; // "usermod_bme280.h" -- Uses "standard" HW_I2C pins + case PinOwner::UM_BH1750 : return(F("BH1750 (UM)")); break; // "usermod_bh1750.h" -- Uses "standard" HW_I2C pins + case PinOwner::UM_SdCard : return(F("SD-Card (UM)")); break; // "usermod_sd_card.h" -- Uses SPI pins + + case PinOwner::UM_Example : return(F("example (UM)")); break; // unspecified usermod + case PinOwner::UM_Unspecified : return(F("usermod (UM)")); break; // unspecified usermod + } + return(F("other")); // should not happen +} + +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 >= NUM_DIGITAL_PINS) return(F("")); // GPIO number too high + //if (gpio >= GPIO_PIN_COUNT) return(F("n/a")); + + // audioreactive settings - unfortunately, these are hiddden inside usermod now :-( + // if((gpio == audioPin) && (dmType == 0)) return(F("analog audio in")); + // if((gpio == i2ssdPin) && (dmType > 0)) return(F("I2S SD")); + // if((gpio == i2swsPin) && (dmType > 0)) return(F("I2S WS")); + // if((gpio == i2sckPin) && (dmType > 0) && (dmType != 5)) return(F("I2S SCK")); + // if((gpio == mclkPin) && ((dmType == 2) || (dmType == 4))) return(F("I2S MCLK")); + + // hardware special purpose PINS + if(gpio == hardwareTX) return(F("Serial TX")); // Serial (debug monitor) TX pin (usually GPIO1) + if(gpio == hardwareRX) return(F("Serial RX")); // Serial (debug monitor) RX pin (usually GPIO3) + if((gpio == i2c_sda) || (gpio == HW_PIN_SDA)) return(F("I2C SDA")); + if((gpio == i2c_scl) || (gpio == HW_PIN_SCL)) return(F("I2C SCL")); + if((gpio == spi_sclk) || (gpio == HW_PIN_CLOCKSPI)) return(F("SPI CLK")); + if((gpio == spi_mosi) || (gpio == HW_PIN_DATASPI)) return(F("SPI MOSI")); + if((gpio == spi_miso) || (gpio == HW_PIN_MISOSPI)) return(F("SPI MISO")); + if((gpio == HW_PIN_CSSPI)) return(F("SPI SS")); // no part of usermod default settings + + // special PINS + #if defined(LED_BUILTIN) || defined(BUILTIN_LED) + if (gpio == LED_BUILTIN) return(F("might be onboard LED")); + #endif + #if defined(STATUSLED) + #endif + + if (!isPinOk(gpio, false)) return(F("")); + +#if 0 + // analog pin infos - experimental ! + #ifdef ARDUINO_ARCH_ESP32 + // ADC PINs - not for 8266 + if (digitalPinToAnalogChannel(gpio) >= 0) { // ADC pin + #ifdef SOC_ADC_CHANNEL_NUM + if (digitalPinToAnalogChannel(gpio) < SOC_ADC_CHANNEL_NUM(0)) return(F("ADC-1")); // for ESP32-S3, ESP32-S2, ESP32-C3 + #else + if (digitalPinToAnalogChannel(gpio) < 8) return(F("ADC-1")); // for classic ESP32 + #endif + else return(F("ADC-2")); + } + #endif +#endif + + return(F("")); // default - nothing special to say +} + +// WLEDMM end + /// Actual allocation/deallocation routines bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) { @@ -25,6 +124,7 @@ 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); @@ -60,6 +160,7 @@ 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); @@ -121,6 +222,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by 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 @@ -150,6 +252,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by 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 @@ -182,6 +285,7 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) 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 @@ -196,6 +300,7 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) 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 diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index db211961..2166e934 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -108,7 +108,8 @@ class PinManagerClass { bool isPinOk(byte gpio, bool output = true); PinOwner getPinOwner(byte gpio); - + String getPinOwnerText(int gpio); // WLEDMM + String getPinSpecialText(int gpio); // WLEDMM #ifdef ARDUINO_ARCH_ESP32 byte allocateLedc(byte channels); void deallocateLedc(byte pos, byte channels); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index b2ccebb1..ff5402f1 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -470,6 +470,27 @@ void WLED::setup() DEBUG_PRINTF("Arduino Event core=%d\n", int(ARDUINO_EVENT_RUNNING_CORE)); #endif #endif + + // WLEDMM : dump GPIO infos (experimental, UI integration pending) + #ifdef WLED_DEBUG + Serial.println(F("WLED initialization completed.")); + Serial.println(F("\nGPIO\t| Assigned to\t\t| Info")); + Serial.println(F("--------|-----------------------|------------")); + for(int pinNr = 0; pinNr < 50; pinNr++) { // 49 = highest PIN on ESP32-S3 + if(pinManager.isPinOk(pinNr, false)) { + if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // comment out to also show unused GPIO pins + bool is_inOut = pinManager.isPinOk(pinNr, true); + Serial.printf("%s %2d\t %-18s\t %s\n", + (is_inOut?"i/o":"in "), + pinNr, + pinManager.getPinOwnerText(pinNr).c_str(), + pinManager.getPinSpecialText(pinNr).c_str() + ); + } + } + Serial.println(); + #endif + // WLEDMM end } void WLED::beginStrip()