Merge branch 'master' into dev
This commit is contained in:
		| @@ -8,12 +8,15 @@ | ||||
| # Please uncomment one of the lines below to select your board(s) | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | ||||
| # Travis CI binaries (comment this out with a ';' when building for your own board) | ||||
| ;default_envs = travis_esp8266, travis_esp32 | ||||
| # Travis CI binaries (use `platformio_override.ini` when building for your own board; see `platformio_override.ini.sample` for an example) | ||||
| ; default_envs = travis_esp8266, travis_esp32 | ||||
|  | ||||
| # Release binaries | ||||
| default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth | ||||
|  | ||||
| # Build everything | ||||
| ; default_envs = esp32dev, esp8285_4CH_MagicHome, esp8285_4CH_H801, codm-controller-0.6-rev2, codm-controller-0.6, esp32s2_saola, d1_mini_5CH_Shojo_PCB, d1_mini, sp501e, travis_esp8266, travis_esp32, nodemcuv2, esp32_eth, anavi_miracle_controller, esp07, esp01_1m_full, m5atom, h803wf, d1_mini_ota, heltec_wifi_kit_8, esp8285_5CH_H801, d1_mini_debug, wemos_shield_esp32, elekstube_ips | ||||
|  | ||||
| # Single binaries (uncomment your board) | ||||
| ; default_envs = elekstube_ips | ||||
| ; default_envs = nodemcuv2 | ||||
| @@ -399,7 +402,7 @@ build_flags = ${common.build_flags_esp32} | ||||
|   -D TEMPERATURE_PIN=23 | ||||
| lib_deps = ${esp32.lib_deps} | ||||
|   OneWire@~2.3.5 | ||||
|   U8g2@~2.28.11 | ||||
|   olikraus/U8g2 @ ^2.28.8 | ||||
|  | ||||
| [env:m5atom] | ||||
| board = esp32dev | ||||
| @@ -482,4 +485,6 @@ build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_D | ||||
|   -D SPI_FREQUENCY=40000000 | ||||
|   -D USER_SETUP_LOADED | ||||
| monitor_filters = esp32_exception_decoder | ||||
| lib_deps = ${esp32.lib_deps} TFT_eSPI | ||||
| lib_deps = | ||||
|   ${esp32.lib_deps} | ||||
|   TFT_eSPI @ ^2.3.70 | ||||
|   | ||||
| @@ -306,22 +306,26 @@ class Animated_Staircase : public Usermod { | ||||
|  | ||||
|   public: | ||||
|     void setup() { | ||||
|       // standardize invalid pin numbers to -1 | ||||
|       if (topPIRorTriggerPin    < 0) topPIRorTriggerPin    = -1; | ||||
|       if (topEchoPin            < 0) topEchoPin            = -1; | ||||
|       if (bottomPIRorTriggerPin < 0) bottomPIRorTriggerPin = -1; | ||||
|       if (bottomEchoPin         < 0) bottomEchoPin         = -1; | ||||
|       // allocate pins | ||||
|       if (topPIRorTriggerPin >= 0) { | ||||
|         if (!pinManager.allocatePin(topPIRorTriggerPin,useUSSensorTop)) | ||||
|           topPIRorTriggerPin = -1; | ||||
|       } | ||||
|       if (topEchoPin >= 0) { | ||||
|         if (!pinManager.allocatePin(topEchoPin,false)) | ||||
|           topEchoPin = -1; | ||||
|       } | ||||
|       if (bottomPIRorTriggerPin >= 0) { | ||||
|         if (!pinManager.allocatePin(bottomPIRorTriggerPin,useUSSensorBottom)) | ||||
|           bottomPIRorTriggerPin = -1; | ||||
|       } | ||||
|       if (bottomEchoPin >= 0) { | ||||
|         if (!pinManager.allocatePin(bottomEchoPin,false)) | ||||
|           bottomEchoPin = -1; | ||||
|       PinManagerPinType pins[4] = { | ||||
|         { topPIRorTriggerPin, useUSSensorTop }, | ||||
|         { topEchoPin, false }, | ||||
|         { bottomPIRorTriggerPin, useUSSensorBottom }, | ||||
|         { bottomEchoPin, false }, | ||||
|       }; | ||||
|       // NOTE: this *WILL* return TRUE if all the pins are set to -1. | ||||
|       //       this is *BY DESIGN*. | ||||
|       if (!pinManager.allocateMultiplePins(pins, 4, PinOwner::UM_AnimatedStaircase)) { | ||||
|         topPIRorTriggerPin = -1; | ||||
|         topEchoPin = -1; | ||||
|         bottomPIRorTriggerPin = -1; | ||||
|         bottomEchoPin = -1; | ||||
|         enabled = false; | ||||
|       } | ||||
|       enable(enabled); | ||||
|       initDone = true; | ||||
| @@ -484,10 +488,10 @@ class Animated_Staircase : public Usermod { | ||||
|             (oldBottomAPin != bottomPIRorTriggerPin) || | ||||
|             (oldBottomBPin != bottomEchoPin)) { | ||||
|           changed = true; | ||||
|           pinManager.deallocatePin(oldTopAPin); | ||||
|           pinManager.deallocatePin(oldTopBPin); | ||||
|           pinManager.deallocatePin(oldBottomAPin); | ||||
|           pinManager.deallocatePin(oldBottomBPin); | ||||
|           pinManager.deallocatePin(oldTopAPin, PinOwner::UM_AnimatedStaircase); | ||||
|           pinManager.deallocatePin(oldTopBPin, PinOwner::UM_AnimatedStaircase); | ||||
|           pinManager.deallocatePin(oldBottomAPin, PinOwner::UM_AnimatedStaircase); | ||||
|           pinManager.deallocatePin(oldBottomBPin, PinOwner::UM_AnimatedStaircase); | ||||
|         } | ||||
|         if (changed) setup(); | ||||
|       } | ||||
|   | ||||
| @@ -58,12 +58,12 @@ public: | ||||
|   void setMinutesTens()                           { setDigit(MINUTES_TENS); } | ||||
|   void setHoursOnes()                             { setDigit(HOURS_ONES); } | ||||
|   void setHoursTens()                             { setDigit(HOURS_TENS); } | ||||
|   bool isSecondsOnes()                            { return (digits_map&SECONDS_ONES_MAP > 0); } | ||||
|   bool isSecondsTens()                            { return (digits_map&SECONDS_TENS_MAP > 0); } | ||||
|   bool isMinutesOnes()                            { return (digits_map&MINUTES_ONES_MAP > 0); } | ||||
|   bool isMinutesTens()                            { return (digits_map&MINUTES_TENS_MAP > 0); } | ||||
|   bool isHoursOnes()                              { return (digits_map&HOURS_ONES_MAP > 0); } | ||||
|   bool isHoursTens()                              { return (digits_map&HOURS_TENS_MAP > 0); } | ||||
|   bool isSecondsOnes()                            { return ((digits_map & SECONDS_ONES_MAP) > 0); } | ||||
|   bool isSecondsTens()                            { return ((digits_map & SECONDS_TENS_MAP) > 0); } | ||||
|   bool isMinutesOnes()                            { return ((digits_map & MINUTES_ONES_MAP) > 0); } | ||||
|   bool isMinutesTens()                            { return ((digits_map & MINUTES_TENS_MAP) > 0); } | ||||
|   bool isHoursOnes()                              { return ((digits_map & HOURS_ONES_MAP) > 0); } | ||||
|   bool isHoursTens()                              { return ((digits_map & HOURS_TENS_MAP) > 0); } | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -201,12 +201,14 @@ public: | ||||
|   { | ||||
|     if (enabled) { | ||||
|       // pin retrieved from cfg.json (readFromConfig()) prior to running setup() | ||||
|       if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin,false)) { | ||||
|       if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin, false, PinOwner::UM_PIR)) { | ||||
|         // PIR Sensor mode INPUT_PULLUP | ||||
|         pinMode(PIRsensorPin, INPUT_PULLUP); | ||||
|         sensorPinState = digitalRead(PIRsensorPin); | ||||
|       } else { | ||||
|         if (PIRsensorPin >= 0) DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed.")); | ||||
|         if (PIRsensorPin >= 0) { | ||||
|           DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed.")); | ||||
|         } | ||||
|         PIRsensorPin = -1;  // allocation failed | ||||
|         enabled = false; | ||||
|       } | ||||
| @@ -367,8 +369,8 @@ public: | ||||
|         if (oldPin != PIRsensorPin && oldPin >= 0) { | ||||
|           // if we are changing pin in settings page | ||||
|           // deallocate old pin | ||||
|           pinManager.deallocatePin(oldPin); | ||||
|           if (pinManager.allocatePin(PIRsensorPin,false)) { | ||||
|           pinManager.deallocatePin(oldPin, PinOwner::UM_PIR); | ||||
|           if (pinManager.allocatePin(PIRsensorPin, false, PinOwner::UM_PIR)) { | ||||
|             pinMode(PIRsensorPin, INPUT_PULLUP); | ||||
|           } else { | ||||
|             // allocation failed | ||||
|   | ||||
| @@ -117,14 +117,19 @@ class UsermodTemperature : public Usermod { | ||||
|         // config says we are enabled | ||||
|         DEBUG_PRINTLN(F("Allocating temperature pin...")); | ||||
|         // pin retrieved from cfg.json (readFromConfig()) prior to running setup() | ||||
|         if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin)) { | ||||
|         if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) { | ||||
|           oneWire = new OneWire(temperaturePin); | ||||
|           if (!oneWire->reset()) | ||||
|           if (!oneWire->reset()) { | ||||
|             sensorFound = false;   // resetting 1-Wire bus yielded an error | ||||
|           else | ||||
|             while ((sensorFound=findSensor()) && retries--) delay(25); // try to find sensor | ||||
|           } else { | ||||
|             while ((sensorFound=findSensor()) && retries--) { | ||||
|               delay(25); // try to find sensor | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           if (temperaturePin >= 0) DEBUG_PRINTLN(F("Temperature pin allocation failed.")); | ||||
|           if (temperaturePin >= 0) { | ||||
|             DEBUG_PRINTLN(F("Temperature pin allocation failed.")); | ||||
|           } | ||||
|           temperaturePin = -1;  // allocation failed | ||||
|           sensorFound = false; | ||||
|         } | ||||
| @@ -275,7 +280,7 @@ class UsermodTemperature : public Usermod { | ||||
|           DEBUG_PRINTLN(F("Re-init temperature.")); | ||||
|           // deallocate pin and release memory | ||||
|           delete oneWire; | ||||
|           pinManager.deallocatePin(temperaturePin); | ||||
|           pinManager.deallocatePin(temperaturePin, PinOwner::UM_Temperature); | ||||
|           temperaturePin = newTemperaturePin; | ||||
|           // initialise | ||||
|           setup(); | ||||
|   | ||||
| @@ -258,7 +258,7 @@ class MultiRelay : public Usermod { | ||||
|       // pins retrieved from cfg.json (readFromConfig()) prior to running setup() | ||||
|       for (uint8_t i=0; i<MULTI_RELAY_MAX_RELAYS; i++) { | ||||
|         if (_relay[i].pin<0) continue; | ||||
|         if (!pinManager.allocatePin(_relay[i].pin,true)) { | ||||
|         if (!pinManager.allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) { | ||||
|           _relay[i].pin = -1;  // allocation failed | ||||
|         } else { | ||||
|           switchRelay(i, _relay[i].state = (bool)bri); | ||||
| @@ -381,12 +381,14 @@ class MultiRelay : public Usermod { | ||||
|         // deallocate all pins 1st | ||||
|         for (uint8_t i=0; i<MULTI_RELAY_MAX_RELAYS; i++) | ||||
|           if (oldPin[i]>=0) { | ||||
|             pinManager.deallocatePin(oldPin[i]); | ||||
|             pinManager.deallocatePin(oldPin[i], PinOwner::UM_MultiRelay); | ||||
|           } | ||||
|         // allocate new pins | ||||
|         for (uint8_t i=0; i<MULTI_RELAY_MAX_RELAYS; i++) { | ||||
|           if (_relay[i].pin>=0 && pinManager.allocatePin(_relay[i].pin,true)) { | ||||
|             if (!_relay[i].external) switchRelay(i, _relay[i].state = (bool)bri); | ||||
|           if (_relay[i].pin>=0 && pinManager.allocatePin(_relay[i].pin, true, PinOwner::UM_MultiRelay)) { | ||||
|             if (!_relay[i].external) { | ||||
|               switchRelay(i, _relay[i].state = (bool)bri); | ||||
|             } | ||||
|           } else { | ||||
|             _relay[i].pin = -1; | ||||
|           } | ||||
|   | ||||
| @@ -13,7 +13,7 @@ class RgbRotaryEncoderUsermod : public Usermod | ||||
|     BusDigital *ledBus; | ||||
|     /* | ||||
|     * Green - eb - Q4 - 32 | ||||
|     * Red - ea - Q1 - 15 | ||||
|     * Red   - ea - Q1 - 15 | ||||
|     * Black - sw - Q2 - 12 | ||||
|     */ | ||||
|     ESPRotary *rotaryEncoder; | ||||
| @@ -39,13 +39,10 @@ class RgbRotaryEncoderUsermod : public Usermod | ||||
|  | ||||
|     void initRotaryEncoder() | ||||
|     { | ||||
|       if (!pinManager.allocatePin(eaIo, false)) { | ||||
|       PinManagerPinType pins[2] = { { eaIo, false }, { ebIo, false } }; | ||||
|       if (!pinManager.allocateMultiplePins(pins, 2, UM_RGBRotaryEncoder)) { | ||||
|         eaIo = -1; | ||||
|       } | ||||
|       if (!pinManager.allocatePin(ebIo, false)) { | ||||
|         ebIo = -1; | ||||
|       } | ||||
|       if (eaIo == -1 || ebIo == -1) { | ||||
|         cleanup(); | ||||
|         return; | ||||
|       } | ||||
| @@ -111,10 +108,12 @@ class RgbRotaryEncoderUsermod : public Usermod | ||||
|     { | ||||
|       // Only deallocate pins if we allocated them ;) | ||||
|       if (eaIo != -1) { | ||||
|         pinManager.deallocatePin(eaIo); | ||||
|         pinManager.deallocatePin(eaIo, PinOwner::UM_RGBRotaryEncoder); | ||||
|         eaIo = -1; | ||||
|       } | ||||
|       if (ebIo != -1) { | ||||
|         pinManager.deallocatePin(ebIo); | ||||
|         pinManager.deallocatePin(ebIo, PinOwner::UM_RGBRotaryEncoder); | ||||
|         ebIo = -1; | ||||
|       } | ||||
|  | ||||
|       delete rotaryEncoder; | ||||
| @@ -304,8 +303,8 @@ class RgbRotaryEncoderUsermod : public Usermod | ||||
|           } | ||||
|  | ||||
|           if (eaIo != oldEaIo || ebIo != oldEbIo || stepsPerClick != oldStepsPerClick || incrementPerClick != oldIncrementPerClick) { | ||||
|             pinManager.deallocatePin(oldEaIo); | ||||
|             pinManager.deallocatePin(oldEbIo); | ||||
|             pinManager.deallocatePin(oldEaIo, PinOwner::UM_RGBRotaryEncoder); | ||||
|             pinManager.deallocatePin(oldEbIo, PinOwner::UM_RGBRotaryEncoder); | ||||
|              | ||||
|             delete rotaryEncoder; | ||||
|             initRotaryEncoder(); | ||||
|   | ||||
| @@ -168,14 +168,12 @@ class FourLineDisplayUsermod : public Usermod { | ||||
|     // network here | ||||
|     void setup() { | ||||
|       if (type == NONE) return; | ||||
|       bool allocated = false; | ||||
|       byte i; | ||||
|       if (type == SSD1306_SPI || type == SSD1306_SPI64) { | ||||
|         for (i=0; i<5; i++) if (!pinManager.allocatePin(ioPin[i])) { allocated=true; break; } | ||||
|         if (i<5 && allocated) { for (byte i=0; i<5; i++) pinManager.deallocatePin(ioPin[i]); type=NONE; return; } | ||||
|         PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true}, { ioPin[2], true }, { ioPin[3], true}, { ioPin[4], true }}; | ||||
|         if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_FourLineDisplay)) { type=NONE; return; } | ||||
|       } else { | ||||
|         for (i=0; i<2; i++) if (!pinManager.allocatePin(ioPin[i])) { allocated=true; break; } | ||||
|         if (i<2 && allocated) { for (byte i=0; i<5; i++) pinManager.deallocatePin(ioPin[i]); type=NONE; return; } | ||||
|         PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true} }; | ||||
|         if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_FourLineDisplay)) { type=NONE; return; } | ||||
|       } | ||||
|       DEBUG_PRINTLN(F("Allocating display.")); | ||||
|       switch (type) { | ||||
| @@ -240,18 +238,17 @@ class FourLineDisplayUsermod : public Usermod { | ||||
|           break; | ||||
|         default: | ||||
|           u8x8 = nullptr; | ||||
|       } | ||||
|       if (nullptr == u8x8) { | ||||
|           DEBUG_PRINTLN(F("Display init failed.")); | ||||
|           for (byte i=0; i<5 && ioPin[i]>=0; i++) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay); | ||||
|           type = NONE; | ||||
|           return; | ||||
|       } | ||||
|  | ||||
|       initDone = true; | ||||
|       if (u8x8 != nullptr) { | ||||
|         DEBUG_PRINTLN(F("Starting display.")); | ||||
|         (static_cast<U8X8*>(u8x8))->begin(); | ||||
|       } else { | ||||
|         DEBUG_PRINTLN(F("Display init failed.")); | ||||
|         type = NONE; | ||||
|         return; | ||||
|       } | ||||
|       DEBUG_PRINTLN(F("Starting display.")); | ||||
|       u8x8->begin(); | ||||
|       setFlipMode(flip); | ||||
|       setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 | ||||
|       setPowerSave(0); | ||||
| @@ -277,40 +274,40 @@ class FourLineDisplayUsermod : public Usermod { | ||||
|      */ | ||||
|     void setFlipMode(uint8_t mode) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setFlipMode(mode); | ||||
|       u8x8->setFlipMode(mode); | ||||
|     } | ||||
|     void setContrast(uint8_t contrast) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setContrast(contrast); | ||||
|       u8x8->setContrast(contrast); | ||||
|     } | ||||
|     void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setFont(u8x8_font_chroma48medium8_r); | ||||
|       if (!ignoreLH && lineHeight==2) (static_cast<U8X8*>(u8x8))->draw1x2String(col, row, string); | ||||
|       else                            (static_cast<U8X8*>(u8x8))->drawString(col, row, string); | ||||
|       u8x8->setFont(u8x8_font_chroma48medium8_r); | ||||
|       if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string); | ||||
|       else                            u8x8->drawString(col, row, string); | ||||
|     } | ||||
|     void draw2x2String(uint8_t col, uint8_t row, const char *string) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setFont(u8x8_font_chroma48medium8_r); | ||||
|       (static_cast<U8X8*>(u8x8))->draw2x2String(col, row, string); | ||||
|       u8x8->setFont(u8x8_font_chroma48medium8_r); | ||||
|       u8x8->draw2x2String(col, row, string); | ||||
|     } | ||||
|     void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setFont(font); | ||||
|       if (!ignoreLH && lineHeight==2) (static_cast<U8X8*>(u8x8))->draw1x2Glyph(col, row, glyph); | ||||
|       else                            (static_cast<U8X8*>(u8x8))->drawGlyph(col, row, glyph); | ||||
|       u8x8->setFont(font); | ||||
|       if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph); | ||||
|       else                            u8x8->drawGlyph(col, row, glyph); | ||||
|     } | ||||
|     uint8_t getCols() { | ||||
|       if (type==NONE) return 0; | ||||
|       return (static_cast<U8X8*>(u8x8))->getCols(); | ||||
|       return u8x8->getCols(); | ||||
|     } | ||||
|     void clear() { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->clear(); | ||||
|       u8x8->clear(); | ||||
|     } | ||||
|     void setPowerSave(uint8_t save) { | ||||
|       if (type==NONE) return; | ||||
|       (static_cast<U8X8*>(u8x8))->setPowerSave(save); | ||||
|       u8x8->setPowerSave(save); | ||||
|     } | ||||
|  | ||||
|     void center(String &line, uint8_t width) { | ||||
| @@ -725,9 +722,9 @@ class FourLineDisplayUsermod : public Usermod { | ||||
|         bool pinsChanged = false; | ||||
|         for (byte i=0; i<5; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; } | ||||
|         if (pinsChanged || type!=newType) { | ||||
|           if (type != NONE) delete (static_cast<U8X8*>(u8x8)); | ||||
|           if (type != NONE) delete u8x8; | ||||
|           for (byte i=0; i<5; i++) { | ||||
|             if (ioPin[i]>=0) pinManager.deallocatePin(ioPin[i]); | ||||
|             if (ioPin[i]>=0) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay); | ||||
|             ioPin[i] = newPin[i]; | ||||
|           } | ||||
|           if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1 | ||||
|   | ||||
| @@ -76,7 +76,7 @@ private: | ||||
|   unsigned char Enc_B; | ||||
|   unsigned char Enc_A_prev = 0; | ||||
|  | ||||
|   bool currentEffectAndPaleeteInitialized = false; | ||||
|   bool currentEffectAndPaletteInitialized = false; | ||||
|   uint8_t effectCurrentIndex = 0; | ||||
|   uint8_t effectPaletteIndex = 0; | ||||
|  | ||||
| @@ -97,9 +97,17 @@ public: | ||||
|      */ | ||||
|   void setup() | ||||
|   { | ||||
|     if (!pinManager.allocatePin(pinA)) { enabled = false; return;} | ||||
|     if (!pinManager.allocatePin(pinB)) { pinManager.deallocatePin(pinA); enabled = false; return; } | ||||
|     if (!pinManager.allocatePin(pinC)) { pinManager.deallocatePin(pinA); pinManager.deallocatePin(pinB); enabled = false; return; } | ||||
|     PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } }; | ||||
|     if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) { | ||||
|       // BUG: configuring this usermod with conflicting pins | ||||
|       //      will cause it to de-allocate pins it does not own | ||||
|       //      (at second config) | ||||
|       //      This is the exact type of bug solved by pinManager | ||||
|       //      tracking the owner tags.... | ||||
|       pinA = pinB = pinC = -1; | ||||
|       enabled = false; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     pinMode(pinA, INPUT_PULLUP); | ||||
|     pinMode(pinB, INPUT_PULLUP); | ||||
| @@ -152,7 +160,7 @@ public: | ||||
|     // Initialize effectCurrentIndex and effectPaletteIndex to | ||||
|     // current state. We do it here as (at least) effectCurrent | ||||
|     // is not yet initialized when setup is called. | ||||
|     if (!currentEffectAndPaleeteInitialized) { | ||||
|     if (!currentEffectAndPaletteInitialized) { | ||||
|       findCurrentEffectAndPalette(); | ||||
|     } | ||||
|  | ||||
| @@ -248,7 +256,7 @@ public: | ||||
|   } | ||||
|  | ||||
|   void findCurrentEffectAndPalette() { | ||||
|     currentEffectAndPaleeteInitialized = true; | ||||
|     currentEffectAndPaletteInitialized = true; | ||||
|     for (uint8_t i = 0; i < strip.getModeCount(); i++) { | ||||
|       //byte value = modes_alpha_indexes[i]; | ||||
|       if (modes_alpha_indexes[i] == effectCurrent) { | ||||
| @@ -455,9 +463,9 @@ public: | ||||
|       DEBUG_PRINTLN(F(" config (re)loaded.")); | ||||
|       // changing parameters from settings page | ||||
|       if (pinA!=newDTpin || pinB!=newCLKpin || pinC!=newSWpin) { | ||||
|         pinManager.deallocatePin(pinA); | ||||
|         pinManager.deallocatePin(pinB); | ||||
|         pinManager.deallocatePin(pinC); | ||||
|         pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI); | ||||
|         pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI); | ||||
|         pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI); | ||||
|         pinA = newDTpin; | ||||
|         pinB = newCLKpin; | ||||
|         pinC = newSWpin; | ||||
|   | ||||
| @@ -916,7 +916,9 @@ const char JSON_palette_names[] PROGMEM = R"=====([ | ||||
| "Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", | ||||
| "Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", | ||||
| "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", | ||||
| "Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2" | ||||
| "Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2","Retro Clown","Candy","Toxy Reaf","Fairy Reaf", | ||||
| "Semi Blue","Pink Candy","Red Reaf","Aqua Flash","Yelblu Hot","Lite Light","Red Flash","Blink Red","Red Shift","Red Tide", | ||||
| "Candy2" | ||||
| ])====="; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -125,10 +125,10 @@ class BusDigital : public Bus { | ||||
|   public: | ||||
|   BusDigital(BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start) { | ||||
|     if (!IS_DIGITAL(bc.type) || !bc.count) return; | ||||
|     if (!pinManager.allocatePin(bc.pins[0])) return; | ||||
|     if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return; | ||||
|     _pins[0] = bc.pins[0]; | ||||
|     if (IS_2PIN(bc.type)) { | ||||
|       if (!pinManager.allocatePin(bc.pins[1])) { | ||||
|       if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) { | ||||
|         cleanup(); return; | ||||
|       } | ||||
|       _pins[1] = bc.pins[1]; | ||||
| @@ -208,11 +208,11 @@ class BusDigital : public Bus { | ||||
|  | ||||
|   void cleanup() { | ||||
|     PolyBus::cleanup(_busPtr, _iType); | ||||
|     pinManager.deallocatePin(_pins[0]); | ||||
|     pinManager.deallocatePin(_pins[1]); | ||||
|     _iType = I_NONE; | ||||
|     _valid = false; | ||||
|     _busPtr = nullptr; | ||||
|     pinManager.deallocatePin(_pins[1], PinOwner::BusDigital); | ||||
|     pinManager.deallocatePin(_pins[0], PinOwner::BusDigital); | ||||
|   } | ||||
|  | ||||
|   ~BusDigital() { | ||||
| @@ -249,7 +249,7 @@ class BusPwm : public Bus { | ||||
|  | ||||
|     for (uint8_t i = 0; i < numPins; i++) { | ||||
|       uint8_t currentPin = bc.pins[i]; | ||||
|       if (!pinManager.allocatePin(currentPin)) { | ||||
|       if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) { | ||||
|         deallocatePins(); return; | ||||
|       } | ||||
|       _pins[i] = currentPin; // store only after allocatePin() succeeds | ||||
| @@ -339,7 +339,7 @@ class BusPwm : public Bus { | ||||
|   void deallocatePins() { | ||||
|     uint8_t numPins = NUM_PWM_PINS(_type); | ||||
|     for (uint8_t i = 0; i < numPins; i++) { | ||||
|       pinManager.deallocatePin(_pins[i]); | ||||
|       pinManager.deallocatePin(_pins[i], PinOwner::BusPwm); | ||||
|       if (!pinManager.isPinOk(_pins[i])) continue; | ||||
|       #ifdef ESP8266 | ||||
|       digitalWrite(_pins[i], LOW); //turn off PWM interrupt | ||||
| @@ -469,4 +469,4 @@ class BusManager { | ||||
|   uint8_t numBusses = 0; | ||||
|   Bus* busses[WLED_MAX_BUSSES]; | ||||
| }; | ||||
| #endif | ||||
| #endif | ||||
|   | ||||
| @@ -19,6 +19,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|  | ||||
|   //long vid = doc[F("vid")]; // 2010020 | ||||
|  | ||||
|   #ifdef WLED_USE_ETHERNET | ||||
|   JsonObject ethernet = doc[F("eth")]; | ||||
|   CJSON(ethernetType, ethernet["type"]); | ||||
|   // NOTE: Ethernet configuration takes priority over other use of pins | ||||
|   WLED::instance().initEthernet(); | ||||
|   #endif | ||||
|  | ||||
|   JsonObject id = doc["id"]; | ||||
|   getStringFromJson(cmDNS, id[F("mdns")], 33); | ||||
|   getStringFromJson(serverDescription, id[F("name")], 33); | ||||
| @@ -93,7 +100,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|  | ||||
|   JsonObject hw = doc[F("hw")]; | ||||
|  | ||||
|   // initialize LED pins and lengths prior to other HW | ||||
|   // initialize LED pins and lengths prior to other HW (except for ethernet) | ||||
|   JsonObject hw_led = hw[F("led")]; | ||||
|  | ||||
|   CJSON(ledCount, hw_led[F("total")]); | ||||
| @@ -162,7 +169,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|     for (JsonObject btn : hw_btn_ins) { | ||||
|       CJSON(buttonType[s], btn["type"]); | ||||
|       int8_t pin = btn["pin"][0] | -1; | ||||
|       if (pin > -1 && pinManager.allocatePin(pin,false)) { | ||||
|       if (pin > -1 && pinManager.allocatePin(pin, false, PinOwner::Button)) { | ||||
|         btnPin[s] = pin; | ||||
|         pinMode(btnPin[s], INPUT_PULLUP); | ||||
|       } else { | ||||
| @@ -186,8 +193,10 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|     // new install/missing configuration (button 0 has defaults) | ||||
|     if (fromFS) { | ||||
|       // relies upon only being called once with fromFS == true, which is currently true. | ||||
|       uint8_t s=0; | ||||
|       if (pinManager.allocatePin(btnPin[0],false)) s++; // do not clear button 0 if pin successfully allocated | ||||
|       uint8_t s = 0; | ||||
|       if (pinManager.allocatePin(btnPin[0], false, PinOwner::Button)) { // initialized to #define value BTNPIN, or zero if not defined(!) | ||||
|         ++s; // do not clear default button if allocated successfully  | ||||
|       } | ||||
|       for (; s<WLED_MAX_BUTTONS; s++) { | ||||
|         btnPin[s]           = -1; | ||||
|         buttonType[s]       = BTN_TYPE_NONE; | ||||
| @@ -202,7 +211,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|  | ||||
|   int hw_ir_pin = hw["ir"]["pin"] | -2; // 4 | ||||
|   if (hw_ir_pin > -2) { | ||||
|     if (pinManager.allocatePin(hw_ir_pin,false)) { | ||||
|     if (pinManager.allocatePin(hw_ir_pin, false, PinOwner::IR)) { | ||||
|       irPin = hw_ir_pin; | ||||
|     } else { | ||||
|       irPin = -1; | ||||
| @@ -213,7 +222,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { | ||||
|   JsonObject relay = hw[F("relay")]; | ||||
|   int hw_relay_pin = relay["pin"] | -2; | ||||
|   if (hw_relay_pin > -2) { | ||||
|     if (pinManager.allocatePin(hw_relay_pin,true)) { | ||||
|     if (pinManager.allocatePin(hw_relay_pin,true, PinOwner::Relay)) { | ||||
|       rlyPin = hw_relay_pin; | ||||
|       pinMode(rlyPin, OUTPUT); | ||||
|     } else { | ||||
| @@ -469,6 +478,8 @@ void deserializeConfigFromFS() { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   // NOTE: This routine deserializes *and* applies the configuration | ||||
|   //       Therefore, must also initialize ethernet from this function | ||||
|   deserializeConfig(doc.as<JsonObject>(), true);   | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -292,7 +292,7 @@ | ||||
| #ifdef ESP8266 | ||||
|   #define LEDPIN 2    // GPIO2 (D4) on Wemod D1 mini compatible boards | ||||
| #else | ||||
|   #define LEDPIN 16   // alligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards | ||||
|   #define LEDPIN 16   // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -359,7 +359,7 @@ void _drawOverlayCronixie() | ||||
| } | ||||
|  | ||||
| #else // WLED_DISABLE_CRONIXIE | ||||
| byte getSameCodeLength(char code, int index, char const cronixieDisplay[]) {return 0;} | ||||
| byte getSameCodeLength(char code, int index, char const cronixieDisplay[]) { return 0; } | ||||
| void setCronixie() {} | ||||
| void _overlayCronixie() {} | ||||
| void _drawOverlayCronixie() {} | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
| #ifndef PalettesWLED_h | ||||
| #define PalettesWLED_h | ||||
|  | ||||
| #define GRADIENT_PALETTE_COUNT 43 | ||||
| #define GRADIENT_PALETTE_COUNT 58 | ||||
|  | ||||
| const byte ib_jul01_gp[] PROGMEM = { | ||||
|     0, 194,  1,  1, | ||||
| @@ -631,7 +631,7 @@ const byte temperature_gp[] PROGMEM = { | ||||
|   240,  80,  3,  3, | ||||
|   255,  80,  3,  3}; | ||||
|  | ||||
|   const byte Aurora2[] PROGMEM = { | ||||
|   const byte Aurora2_gp[] PROGMEM = { | ||||
|       0,  17, 177,  13,    //Greenish | ||||
|      64, 121, 242,   5,    //Greenish | ||||
|     128,  25, 173, 121,    //Turquoise | ||||
| @@ -639,6 +639,213 @@ const byte temperature_gp[] PROGMEM = { | ||||
|     255, 171, 101, 221     //Purple | ||||
|   }; | ||||
|  | ||||
|   // Gradient palette "bhw1_01_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_01.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 12 bytes of program space. | ||||
|  | ||||
| const byte retro_clown_gp[] PROGMEM = { | ||||
|     0, 227,101,  3, | ||||
|   117, 194, 18, 19, | ||||
|   255,  92,  8,192}; | ||||
|  | ||||
| // Gradient palette "bhw1_04_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_04.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 20 bytes of program space. | ||||
|  | ||||
| const byte candy_gp[] PROGMEM = { | ||||
|     0, 229,227,  1, | ||||
|    15, 227,101,  3, | ||||
|   142,  40,  1, 80, | ||||
|   198,  17,  1, 79, | ||||
|   255,   0,  0, 45}; | ||||
|  | ||||
| // Gradient palette "bhw1_05_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_05.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 8 bytes of program space. | ||||
|  | ||||
| const byte toxy_reaf_gp[] PROGMEM = { | ||||
|     0,   1,221, 53, | ||||
|   255,  73,  3,178}; | ||||
|  | ||||
| // Gradient palette "bhw1_06_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_06.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 16 bytes of program space. | ||||
|  | ||||
| const byte  fairy_reaf_gp[] PROGMEM = { | ||||
|     0, 184,  1,128, | ||||
|   160,   1,193,182, | ||||
|   219, 153,227,190, | ||||
|   255, 255,255,255}; | ||||
|  | ||||
| // Gradient palette "bhw1_14_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_14.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 36 bytes of program space. | ||||
|  | ||||
| const byte semi_blue_gp[] PROGMEM = { | ||||
|     0,   0,  0,  0, | ||||
|    12,   1,  1,  3, | ||||
|    53,   8,  1, 22, | ||||
|    80,   4,  6, 89, | ||||
|   119,   2, 25,216, | ||||
|   145,   7, 10, 99, | ||||
|   186,  15,  2, 31, | ||||
|   233,   2,  1,  5, | ||||
|   255,   0,  0,  0}; | ||||
|  | ||||
| // Gradient palette "bhw1_three_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_three.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 32 bytes of program space. | ||||
|  | ||||
| const byte pink_candy_gp[] PROGMEM = { | ||||
|     0, 255,255,255, | ||||
|    45,   7, 12,255, | ||||
|   112, 227,  1,127, | ||||
|   112, 227,  1,127, | ||||
|   140, 255,255,255, | ||||
|   155, 227,  1,127, | ||||
|   196,  45,  1, 99, | ||||
|   255, 255,255,255}; | ||||
|  | ||||
| // Gradient palette "bhw1_w00t_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_w00t.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 16 bytes of program space. | ||||
|  | ||||
| const byte red_reaf_gp[] PROGMEM = { | ||||
|     0,   3, 13, 43, | ||||
|   104,  78,141,240, | ||||
|   188, 255,  0,  0, | ||||
|   255,  28,  1,  1}; | ||||
|  | ||||
|  | ||||
| // Gradient palette "bhw2_23_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_23.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Red & Flash in SR | ||||
| // Size: 28 bytes of program space. | ||||
|  | ||||
| const byte aqua_flash_gp[] PROGMEM = { | ||||
|     0,   0,  0,  0, | ||||
|    66,  57,227,233, | ||||
|    96, 255,255,  8, | ||||
|   124, 255,255,255, | ||||
|   153, 255,255,  8, | ||||
|   188,  57,227,233, | ||||
|   255,   0,  0,  0}; | ||||
|  | ||||
| // Gradient palette "bhw2_xc_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_xc.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // YBlue in SR | ||||
| // Size: 28 bytes of program space. | ||||
|  | ||||
| const byte yelblu_hot_gp[] PROGMEM = { | ||||
|     0,   4,  2,  9, | ||||
|    58,  16,  0, 47, | ||||
|   122,  24,  0, 16, | ||||
|   158, 144,  9,  1, | ||||
|   183, 179, 45,  1, | ||||
|   219, 220,114,  2, | ||||
|   255, 234,237,  1}; | ||||
|  | ||||
|  // Gradient palette "bhw2_45_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_45.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 24 bytes of program space. | ||||
|  | ||||
| const byte lite_light_gp[] PROGMEM = { | ||||
|     0,   0,  0,  0, | ||||
|     9,   1,  1,  1, | ||||
|    40,   5,  5,  6, | ||||
|    66,   5,  5,  6, | ||||
|   101,  10,  1, 12, | ||||
|   255,   0,  0,  0}; | ||||
|  | ||||
| // Gradient palette "bhw2_22_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_22.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Pink Plasma in SR | ||||
| // Size: 20 bytes of program space. | ||||
|  | ||||
| const byte red_flash_gp[] PROGMEM = { | ||||
|     0,   0,  0,  0, | ||||
|    99, 227,  1,  1, | ||||
|   130, 249,199, 95, | ||||
|   155, 227,  1,  1, | ||||
|   255,   0,  0,  0}; | ||||
|  | ||||
| // Gradient palette "bhw3_40_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_40.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 32 bytes of program space. | ||||
|  | ||||
| const byte blink_red_gp[] PROGMEM = { | ||||
|     0,   1,  1,  1, | ||||
|    43,   4,  1, 11, | ||||
|    76,  10,  1,  3, | ||||
|   109, 161,  4, 29, | ||||
|   127, 255, 86,123, | ||||
|   165, 125, 16,160, | ||||
|   204,  35, 13,223, | ||||
|   255,  18,  2, 18}; | ||||
|  | ||||
| // Gradient palette "bhw3_52_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_52.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Yellow2Blue in SR | ||||
| // Size: 28 bytes of program space. | ||||
|  | ||||
| const byte red_shift_gp[] PROGMEM = { | ||||
|     0,  31,  1, 27, | ||||
|    45,  34,  1, 16, | ||||
|    99, 137,  5,  9, | ||||
|   132, 213,128, 10, | ||||
|   175, 199, 22,  1, | ||||
|   201, 199,  9,  6, | ||||
|   255,   1,  0,  1}; | ||||
|  | ||||
| // Gradient palette "bhw4_097_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_097.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Yellow2Red in SR | ||||
| // Size: 44 bytes of program space. | ||||
|  | ||||
| const byte red_tide_gp[] PROGMEM = { | ||||
|     0, 247,  5,  0, | ||||
|    28, 255, 67,  1, | ||||
|    43, 234, 88, 11, | ||||
|    58, 234,176, 51, | ||||
|    84, 229, 28,  1, | ||||
|   114, 113, 12,  1, | ||||
|   140, 255,225, 44, | ||||
|   168, 113, 12,  1, | ||||
|   196, 244,209, 88, | ||||
|   216, 255, 28,  1, | ||||
|   255,  53,  1,  1}; | ||||
|  | ||||
| // Gradient palette "bhw4_017_gp", originally from | ||||
| // http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_017.png.index.html | ||||
| // converted for FastLED with gammas (2.6, 2.2, 2.5) | ||||
| // Size: 40 bytes of program space. | ||||
|  | ||||
| const byte candy2_gp[] PROGMEM = { | ||||
|     0,  39, 33, 34, | ||||
|    25,   4,  6, 15, | ||||
|    48,  49, 29, 22, | ||||
|    73, 224,173,  1, | ||||
|    89, 177, 35,  5, | ||||
|   130,   4,  6, 15, | ||||
|   163, 255,114,  6, | ||||
|   186, 224,173,  1, | ||||
|   211,  39, 33, 34, | ||||
|   255,   1,  1,  1}; | ||||
|  | ||||
| // Single array of defined cpt-city color palettes. | ||||
| // This will let us programmatically choose one based on | ||||
| // a number, rather than having to activate each explicitly | ||||
| @@ -686,7 +893,22 @@ const byte* const gGradientPalettes[] PROGMEM = { | ||||
|   C9_2_gp,                      //52-39 C9 2 | ||||
|   C9_new_gp,                    //53-40 C9 New | ||||
|   temperature_gp,               //54-41 Temperature | ||||
|   Aurora2                       //55-42 Aurora 2 | ||||
|   Aurora2_gp,                   //55-42 Aurora 2 | ||||
|   retro_clown_gp,               //56-43 Retro Clown | ||||
|   candy_gp,                     //57-44 Candy | ||||
|   toxy_reaf_gp,                 //58-45 Toxy Reaf | ||||
|   fairy_reaf_gp,                //59-46 Fairy Reaf | ||||
|   semi_blue_gp,                 //60-47 Semi Blue | ||||
|   pink_candy_gp,                //61-48 Pink Candy | ||||
|   red_reaf_gp,                  //62-49 Red Reaf | ||||
|   aqua_flash_gp,                //63-50 Aqua Flash | ||||
|   yelblu_hot_gp,                //64-51 Yelblu Hot | ||||
|   lite_light_gp,                //65-52 Lite Light | ||||
|   red_flash_gp,                 //66-53 Red Flash | ||||
|   blink_red_gp,                 //67-54 Blink Red | ||||
|   red_shift_gp,                 //68-55 Red Shift | ||||
|   red_tide_gp,                  //69-56 Red Tide | ||||
|   candy2_gp                     //70-57 Candy2 | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,35 +1,110 @@ | ||||
| #include "pin_manager.h" | ||||
| #include "wled.h" | ||||
|  | ||||
| void PinManagerClass::deallocatePin(byte gpio) | ||||
| static void DebugPrintOwnerTag(PinOwner tag) | ||||
| { | ||||
|   if (!isPinOk(gpio, false)) return; | ||||
|   uint32_t q = static_cast<uint8_t>(tag); | ||||
|   if (q) { | ||||
|     DEBUG_PRINTF("0x%02x (%d)", q, q); | ||||
|   } else { | ||||
|     DEBUG_PRINT(F("(no owner)")); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// Actual allocation/deallocation routines | ||||
| bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag) | ||||
| { | ||||
|   if (gpio == 0xFF) return true;           // explicitly allow clients to free -1 as a no-op | ||||
|   if (!isPinOk(gpio, false)) return false; // but return false for any other invalid pin | ||||
|  | ||||
|   // if a non-zero ownerTag, only allow de-allocation if the owner's tag is provided | ||||
|   if ((ownerTag[gpio] != PinOwner::None) && (ownerTag[gpio] != tag)) { | ||||
|     DEBUG_PRINT(F("PIN DEALLOC: IO ")); | ||||
|     DEBUG_PRINT(gpio); | ||||
|     DEBUG_PRINT(F(" allocated by ")); | ||||
|     DebugPrintOwnerTag(ownerTag[gpio]); | ||||
|     DEBUG_PRINT(F(", but attempted de-allocation by ")); | ||||
|     DebugPrintOwnerTag(tag); | ||||
|     return false; | ||||
|   } | ||||
|    | ||||
|   byte by = gpio >> 3; | ||||
|   byte bi = gpio - 8*by; | ||||
|   bitWrite(pinAlloc[by], bi, false); | ||||
|   ownerTag[gpio] = PinOwner::None; | ||||
|   return true; | ||||
| } | ||||
| bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag) | ||||
| { | ||||
|   bool shouldFail = false; | ||||
|   // first verify the pins are OK and not already allocated | ||||
|   for (int i = 0; i < arrayElementCount; i++) { | ||||
|     byte gpio = mptArray[i].pin; | ||||
|     if (gpio == 0xFF) { | ||||
|       // explicit support for io -1 as a no-op (no allocation of pin), | ||||
|       // as this can greatly simplify configuration arrays | ||||
|       continue; | ||||
|     } | ||||
|     if (!isPinOk(gpio, mptArray[i].isOutput)) { | ||||
|       DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: ")); | ||||
|       DEBUG_PRINT(gpio); | ||||
|       DEBUG_PRINTLN(F("")); | ||||
|       shouldFail = true; | ||||
|     } | ||||
|     if (isPinAllocated(gpio)) { | ||||
|       DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));  | ||||
|       DEBUG_PRINT(gpio); | ||||
|       DEBUG_PRINT(F(" already allocated by ")); | ||||
|       DebugPrintOwnerTag(ownerTag[gpio]); | ||||
|       DEBUG_PRINTLN(F("")); | ||||
|       shouldFail = true; | ||||
|     } | ||||
|   } | ||||
|   if (shouldFail) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| bool PinManagerClass::allocatePin(byte gpio, bool output) | ||||
|   // all pins are available .. track each one | ||||
|   for (int i = 0; i < arrayElementCount; i++) { | ||||
|     byte gpio = mptArray[i].pin; | ||||
|     if (gpio == 0xFF) { | ||||
|       // allow callers to include -1 value as non-requested pin | ||||
|       // as this can greatly simplify configuration arrays | ||||
|       continue; | ||||
|     } | ||||
|     byte by = gpio >> 3; | ||||
|     byte bi = gpio - 8*by; | ||||
|     bitWrite(pinAlloc[by], bi, true); | ||||
|     ownerTag[gpio] = tag; | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
| bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) | ||||
| { | ||||
|   if (!isPinOk(gpio, output)) return false; | ||||
|   if (isPinAllocated(gpio)) { | ||||
|     DEBUG_PRINT(F("Attempted duplicate allocation of pin ")); | ||||
|     DEBUG_PRINTLN(gpio); | ||||
|     DEBUG_PRINT(F("PIN ALLOC: Pin "));  | ||||
|     DEBUG_PRINT(gpio); | ||||
|     DEBUG_PRINT(F(" already allocated by ")); | ||||
|     DebugPrintOwnerTag(ownerTag[gpio]); | ||||
|     DEBUG_PRINTLN(F("")); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   byte by = gpio >> 3; | ||||
|   byte bi = gpio - 8*by; | ||||
|   bitWrite(pinAlloc[by], bi, true); | ||||
|   ownerTag[gpio] = tag; | ||||
|    | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool PinManagerClass::isPinAllocated(byte gpio) | ||||
| // 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; | ||||
|   byte by = gpio >> 3; | ||||
|   byte bi = gpio - 8*by; | ||||
|   return bitRead(pinAlloc[by], bi); | ||||
| @@ -46,7 +121,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) | ||||
|   if (gpio < 34) return true; | ||||
|   if (gpio < 40 && !output) return true; //34-39 input only | ||||
|   #endif | ||||
|    | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| @@ -88,4 +163,4 @@ void PinManagerClass::deallocateLedc(byte pos, byte channels) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| PinManagerClass pinManager = PinManagerClass(); | ||||
| PinManagerClass pinManager = PinManagerClass(); | ||||
|   | ||||
| @@ -4,21 +4,92 @@ | ||||
|  * Registers pins so there is no attempt for two interfaces to use the same pin | ||||
|  */ | ||||
| #include <Arduino.h> | ||||
| #include "const.h" // for USERMOD_* values | ||||
|  | ||||
| typedef struct PinManagerPinType { | ||||
|   int8_t  pin; | ||||
|   uint8_t isOutput; | ||||
| } managed_pin_type; | ||||
|  | ||||
| /* | ||||
|  * Allows PinManager to "lock" an allocation to a specific | ||||
|  * owner, so someone else doesn't accidentally de-allocate | ||||
|  * a pin it hasn't allocated.  Also enhances debugging. | ||||
|  *  | ||||
|  * RAM Cost: | ||||
|  *     17 bytes on ESP8266 | ||||
|  *     40 bytes on ESP32 | ||||
|  */ | ||||
| enum struct PinOwner : uint8_t { | ||||
|   None          = 0,            // default == legacy == unspecified owner | ||||
|   // High bit is set for all built-in pin owners | ||||
|   Ethernet      = 0x81, | ||||
|   BusDigital    = 0x82, | ||||
|   BusDigital2   = 0x83, | ||||
|   BusPwm        = 0x84,   // 'BusP' == PWM output using BusPwm | ||||
|   Button        = 0x85,   // 'Butn' == button from configuration | ||||
|   IR            = 0x86,   // 'IR'   == IR receiver pin from configuration | ||||
|   Relay         = 0x87,   // 'Rly'  == Relay pin from configuration | ||||
|   SPI_RAM       = 0x88,   // 'SpiR' == SPI RAM | ||||
|   DebugOut      = 0x89,   // 'Dbg'  == debug output always IO1 | ||||
|   DMX           = 0x8A,   // 'DMX'  == hard-coded to IO2 | ||||
|   // Use UserMod IDs from const.h here | ||||
|   UM_Unspecified       = USERMOD_ID_UNSPECIFIED,        // 0x01 | ||||
|   UM_RGBRotaryEncoder  = USERMOD_ID_UNSPECIFIED,        // 0x01 // No define in const.h for this user module -- consider adding? | ||||
|   UM_Example           = USERMOD_ID_EXAMPLE,            // 0x02 // Usermod "usermod_v2_example.h" | ||||
|   UM_Temperature       = USERMOD_ID_TEMPERATURE,        // 0x03 // Usermod "usermod_temperature.h" | ||||
|   // #define USERMOD_ID_FIXNETSERVICES                  // 0x04 // Usermod "usermod_Fix_unreachable_netservices.h" -- Does not allocate pins | ||||
|   UM_PIR               = USERMOD_ID_PIRSWITCH,          // 0x05 // Usermod "usermod_PIR_sensor_switch.h" | ||||
|   // #define USERMOD_ID_IMU                             // 0x06 // Usermod "usermod_mpu6050_imu.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use | ||||
|   UM_FourLineDisplay   = USERMOD_ID_FOUR_LINE_DISP,     // 0x07 // Usermod "usermod_v2_four_line_display.h | ||||
|   UM_RotaryEncoderUI   = USERMOD_ID_ROTARY_ENC_UI,      // 0x08 // Usermod "usermod_v2_rotary_encoder_ui.h" | ||||
|   // #define USERMOD_ID_AUTO_SAVE                       // 0x09 // Usermod "usermod_v2_auto_save.h" -- Does not allocate pins | ||||
|   // #define USERMOD_ID_DHT                             // 0x0A // Usermod "usermod_dht.h" -- Statically allocates pins, not compatible with pinManager? | ||||
|   // #define USERMOD_ID_MODE_SORT                       // 0x0B // Usermod "usermod_v2_mode_sort.h" -- Does not allocate pins | ||||
|   // #define USERMOD_ID_VL53L0X                         // 0x0C // Usermod "usermod_vl53l0x_gestures.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use | ||||
|   UM_MultiRelay        = USERMOD_ID_MULTI_RELAY,        // 0x0D // Usermod "usermod_multi_relay.h" | ||||
|   UM_AnimatedStaircase = USERMOD_ID_ANIMATED_STAIRCASE, // 0x0E // Usermod "Animated_Staircase.h" | ||||
|   // #define USERMOD_ID_RTC                             // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use | ||||
|   // #define USERMOD_ID_ELEKSTUBE_IPS                   // 0x10 // Usermod "usermod_elekstube_ips.h" -- Uses quite a few pins ... see Hardware.h and User_Setup.h | ||||
|   // #define USERMOD_ID_SN_PHOTORESISTOR                // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager | ||||
| }; | ||||
| static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected"); | ||||
|  | ||||
| class PinManagerClass { | ||||
|   private: | ||||
|   #ifdef ESP8266 | ||||
|   uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits | ||||
|   PinOwner ownerTag[17] = { PinOwner::None }; | ||||
|   #else | ||||
|   uint8_t pinAlloc[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; //40bit, 1 bit per pin, we use all bits | ||||
|   uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels | ||||
|   PinOwner ownerTag[40] = { PinOwner::None }; | ||||
|   #endif | ||||
|  | ||||
|   public: | ||||
|   void deallocatePin(byte gpio); | ||||
|   bool allocatePin(byte gpio, bool output = true); | ||||
|   bool isPinAllocated(byte gpio); | ||||
|   // De-allocates a single pin | ||||
|   bool deallocatePin(byte gpio, PinOwner tag); | ||||
|   // Allocates a single pin, with an owner tag. | ||||
|   // De-allocation requires the same owner tag (or override) | ||||
|   bool allocatePin(byte gpio, bool output, PinOwner tag); | ||||
|   // Allocates all the pins, or allocates none of the pins, with owner tag. | ||||
|   // Provided to simplify error condition handling in clients  | ||||
|   // using more than one pin, such as I2C, SPI, rotary encoders, | ||||
|   // ethernet, etc.. | ||||
|   bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag ); | ||||
|  | ||||
|   #if !defined(ESP8266) // ESP8266 compiler doesn't understand deprecated attribute | ||||
|   [[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]] | ||||
|   #endif | ||||
|   inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); } | ||||
|   #if !defined(ESP8266) // ESP8266 compiler doesn't understand deprecated attribute | ||||
|   [[deprecated("Replaced by three-parameter deallocatePin(gpio, output, ownerTag), for improved debugging")]] | ||||
|   #endif | ||||
|   inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); } | ||||
|  | ||||
|   bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None); | ||||
|   bool isPinOk(byte gpio, bool output = true); | ||||
|  | ||||
|   #ifdef ARDUINO_ARCH_ESP32 | ||||
|   byte allocateLedc(byte channels); | ||||
|   void deallocateLedc(byte pos, byte channels); | ||||
| @@ -26,4 +97,4 @@ class PinManagerClass { | ||||
| }; | ||||
|  | ||||
| extern PinManagerClass pinManager; | ||||
| #endif | ||||
| #endif | ||||
|   | ||||
| @@ -54,6 +54,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|  | ||||
|     #ifdef WLED_USE_ETHERNET | ||||
|     ethernetType = request->arg(F("ETH")).toInt(); | ||||
|     WLED::instance().initEthernet(); | ||||
|     #endif | ||||
|  | ||||
|     char k[3]; k[2] = 0; | ||||
| @@ -77,11 +78,17 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|   { | ||||
|     int t = 0; | ||||
|  | ||||
|     if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin); | ||||
|     if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin); | ||||
|     for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) | ||||
|       if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s])) | ||||
|         pinManager.deallocatePin(btnPin[s]); | ||||
|     if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin, PinOwner::Relay)) { | ||||
|        pinManager.deallocatePin(rlyPin, PinOwner::Relay); | ||||
|     } | ||||
|     if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) { | ||||
|        pinManager.deallocatePin(irPin, PinOwner::IR); | ||||
|     } | ||||
|     for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) { | ||||
|       if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s], PinOwner::Button)) { | ||||
|         pinManager.deallocatePin(btnPin[s], PinOwner::Button); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     uint8_t colorOrder, type, skip; | ||||
|     uint16_t length, start; | ||||
| @@ -126,7 +133,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|  | ||||
|     // upate other pins | ||||
|     int hw_ir_pin = request->arg(F("IR")).toInt(); | ||||
|     if (pinManager.allocatePin(hw_ir_pin,false)) { | ||||
|     if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) { | ||||
|       irPin = hw_ir_pin; | ||||
|     } else { | ||||
|       irPin = -1; | ||||
| @@ -134,7 +141,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|     irEnabled = request->arg(F("IT")).toInt(); | ||||
|  | ||||
|     int hw_rly_pin = request->arg(F("RL")).toInt(); | ||||
|     if (pinManager.allocatePin(hw_rly_pin,true)) { | ||||
|     if (pinManager.allocatePin(hw_rly_pin,true, PinOwner::Relay)) { | ||||
|       rlyPin = hw_rly_pin; | ||||
|     } else { | ||||
|       rlyPin = -1; | ||||
| @@ -145,7 +152,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
|       char bt[4] = "BT"; bt[2] = 48+i; bt[3] = 0; // button pin | ||||
|       char be[4] = "BE"; be[2] = 48+i; be[3] = 0; // button type | ||||
|       int hw_btn_pin = request->arg(bt).toInt(); | ||||
|       if (pinManager.allocatePin(hw_btn_pin,false)) { | ||||
|       if (pinManager.allocatePin(hw_btn_pin,false,PinOwner::Button)) { | ||||
|         btnPin[i] = hw_btn_pin; | ||||
|         pinMode(btnPin[i], INPUT_PULLUP); | ||||
|         buttonType[i] = request->arg(be).toInt(); | ||||
|   | ||||
							
								
								
									
										165
									
								
								wled00/wled.cpp
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								wled00/wled.cpp
									
									
									
									
									
								
							| @@ -177,6 +177,11 @@ void WiFiEvent(WiFiEvent_t event) | ||||
|       break; | ||||
|     case SYSTEM_EVENT_ETH_DISCONNECTED: | ||||
|       DEBUG_PRINT(F("ETH Disconnected")); | ||||
|       // This doesn't really affect ethernet per se, | ||||
|       // as it's only configured once.  Rather, it | ||||
|       // may be necessary to reconnect the WiFi when | ||||
|       // ethernet disconnects, as a way to provide | ||||
|       // alternative access to the device. | ||||
|       forceReconnect = true; | ||||
|       break; | ||||
| #endif | ||||
| @@ -351,20 +356,21 @@ void WLED::setup() | ||||
|   registerUsermods(); | ||||
|  | ||||
|   #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) | ||||
|     if (psramFound()) { | ||||
|       pinManager.allocatePin(16); // GPIO16 reserved for SPI RAM | ||||
|       pinManager.allocatePin(17); // GPIO17 reserved for SPI RAM | ||||
|     } | ||||
|   if (psramFound()) { | ||||
|     // GPIO16/GPIO17 reserved for SPI RAM | ||||
|     managed_pin_type pins[2] = { {16, true}, {17, true} }; | ||||
|     pinManager.allocateMultiplePins(pins, 2, PinOwner::SPI_RAM); | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   //DEBUG_PRINT(F("LEDs inited. heap usage ~")); | ||||
|   //DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap()); | ||||
|  | ||||
| #ifdef WLED_DEBUG | ||||
|   pinManager.allocatePin(1,true); // GPIO1 reserved for debug output | ||||
|   pinManager.allocatePin(1, true, PinOwner::DebugOut); // GPIO1 reserved for debug output | ||||
| #endif | ||||
| #ifdef WLED_USE_DMX //reserve GPIO2 as hardcoded DMX pin | ||||
|   pinManager.allocatePin(2); | ||||
|   pinManager.allocatePin(2, true, PinOwner::DMX); | ||||
| #endif | ||||
|  | ||||
|   for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) btnPin[i] = -1; | ||||
| @@ -509,72 +515,97 @@ void WLED::initAP(bool resetAP) | ||||
|   apActive = true; | ||||
| } | ||||
|  | ||||
| bool WLED::initEthernet() | ||||
| { | ||||
| #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) | ||||
|  | ||||
|   static bool successfullyConfiguredEthernet = false; | ||||
|  | ||||
|   if (successfullyConfiguredEthernet) { | ||||
|     // DEBUG_PRINTLN(F("initE: ETH already successfully configured, ignoring")); | ||||
|     return false; | ||||
|   } | ||||
|   if (ethernetType == WLED_ETH_NONE) { | ||||
|     return false; | ||||
|   } | ||||
|   if (ethernetType >= WLED_NUM_ETH_TYPES) { | ||||
|     DEBUG_PRINT(F("initE: Ignoring attempt for invalid ethernetType ")); DEBUG_PRINTLN(ethernetType); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   DEBUG_PRINT(F("initE: Attempting ETH config: ")); DEBUG_PRINTLN(ethernetType); | ||||
|  | ||||
|   // Ethernet initialization should only succeed once -- else reboot required | ||||
|   ethernet_settings es = ethernetBoards[ethernetType]; | ||||
|   managed_pin_type pinsToAllocate[10] = { | ||||
|     // first six pins are non-configurable | ||||
|     esp32_nonconfigurable_ethernet_pins[0], | ||||
|     esp32_nonconfigurable_ethernet_pins[1], | ||||
|     esp32_nonconfigurable_ethernet_pins[2], | ||||
|     esp32_nonconfigurable_ethernet_pins[3], | ||||
|     esp32_nonconfigurable_ethernet_pins[4], | ||||
|     esp32_nonconfigurable_ethernet_pins[5], | ||||
|     { (int8_t)es.eth_mdc,   true },  // [6] = MDC  is output and mandatory | ||||
|     { (int8_t)es.eth_mdio,  true },  // [7] = MDIO is bidirectional and mandatory | ||||
|     { (int8_t)es.eth_power, true },  // [8] = optional pin, not all boards use | ||||
|     { ((int8_t)0xFE),       false }, // [9] = replaced with eth_clk_mode, mandatory | ||||
|   }; | ||||
|   // update the clock pin.... | ||||
|   if (es.eth_clk_mode == ETH_CLOCK_GPIO0_IN) { | ||||
|     pinsToAllocate[9].pin = 0; | ||||
|     pinsToAllocate[9].isOutput = false; | ||||
|   } else if (es.eth_clk_mode == ETH_CLOCK_GPIO0_OUT) { | ||||
|     pinsToAllocate[9].pin = 0; | ||||
|     pinsToAllocate[9].isOutput = true; | ||||
|   } else if (es.eth_clk_mode == ETH_CLOCK_GPIO16_OUT) { | ||||
|     pinsToAllocate[9].pin = 16; | ||||
|     pinsToAllocate[9].isOutput = true; | ||||
|   } else if (es.eth_clk_mode == ETH_CLOCK_GPIO17_OUT) { | ||||
|     pinsToAllocate[9].pin = 17; | ||||
|     pinsToAllocate[9].isOutput = true; | ||||
|   } else { | ||||
|     DEBUG_PRINT(F("initE: Failing due to invalid eth_clk_mode (")); | ||||
|     DEBUG_PRINT(es.eth_clk_mode); | ||||
|     DEBUG_PRINTLN(F(")")); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   if (!pinManager.allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) { | ||||
|     DEBUG_PRINTLN(F("initE: Failed to allocate ethernet pins")); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   if (!ETH.begin( | ||||
|                 (uint8_t) es.eth_address,  | ||||
|                 (int)     es.eth_power,  | ||||
|                 (int)     es.eth_mdc,  | ||||
|                 (int)     es.eth_mdio,  | ||||
|                 (eth_phy_type_t)   es.eth_type, | ||||
|                 (eth_clock_mode_t) es.eth_clk_mode | ||||
|                 )) { | ||||
|     DEBUG_PRINTLN(F("initC: ETH.begin() failed")); | ||||
|     // de-allocate the allocated pins | ||||
|     for (managed_pin_type mpt : pinsToAllocate) { | ||||
|       pinManager.deallocatePin(mpt.pin, PinOwner::Ethernet); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   successfullyConfiguredEthernet = true; | ||||
|   DEBUG_PRINTLN(F("initC: *** Ethernet successfully configured! ***")); | ||||
|   return true; | ||||
| #else | ||||
|   return false; // Ethernet not enabled for build | ||||
| #endif | ||||
|  | ||||
| } | ||||
|  | ||||
| void WLED::initConnection() | ||||
| { | ||||
|   #ifdef WLED_ENABLE_WEBSOCKETS | ||||
|   ws.onEvent(wsEvent); | ||||
|   #endif | ||||
|  | ||||
| #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) | ||||
|   // Only initialize ethernet board if not NONE | ||||
|   if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { | ||||
|     ethernet_settings es = ethernetBoards[ethernetType]; | ||||
|     // Use PinManager to ensure pins are available for | ||||
|     // ethernet AND to prevent other uses of these pins. | ||||
|     bool s = true; | ||||
|     byte pinsAllocated[4] { 255, 255, 255, 255 }; | ||||
|  | ||||
|     if (s && (s = pinManager.allocatePin((byte)es.eth_power))) { | ||||
|       pinsAllocated[0] = (byte)es.eth_power; | ||||
|     } | ||||
|     if (s && (s = pinManager.allocatePin((byte)es.eth_mdc))) { | ||||
|       pinsAllocated[1] = (byte)es.eth_mdc; | ||||
|     } | ||||
|     if (s && (s = pinManager.allocatePin((byte)es.eth_mdio))) { | ||||
|       pinsAllocated[2] = (byte)es.eth_mdio; | ||||
|     } | ||||
|     switch(es.eth_clk_mode) { | ||||
|       case ETH_CLOCK_GPIO0_IN: | ||||
|         s = pinManager.allocatePin(0, false); | ||||
|         pinsAllocated[3] = 0; | ||||
|         break; | ||||
|       case ETH_CLOCK_GPIO0_OUT: | ||||
|         s = pinManager.allocatePin(0); | ||||
|         pinsAllocated[3] = 0; | ||||
|         break; | ||||
|       case ETH_CLOCK_GPIO16_OUT: | ||||
|         s = pinManager.allocatePin(16); | ||||
|         pinsAllocated[3] = 16; | ||||
|         break; | ||||
|       case ETH_CLOCK_GPIO17_OUT: | ||||
|         s = pinManager.allocatePin(17); | ||||
|         pinsAllocated[3] = 17; | ||||
|         break; | ||||
|       default: | ||||
|         s = false; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     if (s) { | ||||
|       s = ETH.begin( | ||||
|         (uint8_t) es.eth_address,  | ||||
|         (int)     es.eth_power,  | ||||
|         (int)     es.eth_mdc,  | ||||
|         (int)     es.eth_mdio,  | ||||
|         (eth_phy_type_t)   es.eth_type, | ||||
|         (eth_clock_mode_t) es.eth_clk_mode | ||||
|       ); | ||||
|     } | ||||
|      | ||||
|     if (!s) { | ||||
|       DEBUG_PRINTLN(F("Ethernet init failed")); | ||||
|       // de-allocate only those pins allocated before the failure | ||||
|       for (byte p : pinsAllocated) { | ||||
|         pinManager.deallocatePin(p); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   WiFi.disconnect(true);        // close old connections | ||||
| #ifdef ESP8266 | ||||
| @@ -582,7 +613,7 @@ void WLED::initConnection() | ||||
| #endif | ||||
|  | ||||
|   if (staticIP[0] != 0 && staticGateway[0] != 0) { | ||||
|     WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8)); | ||||
|     WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(1, 1, 1, 1)); | ||||
|   } else { | ||||
|     WiFi.config(0U, 0U, 0U); | ||||
|   } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  */ | ||||
|  | ||||
| // version code in format yymmddb (b = daily build) | ||||
| #define VERSION 2108251 | ||||
| #define VERSION 2108261 | ||||
|  | ||||
| //uncomment this if you have a "my_config.h" file you'd like to use | ||||
| //#define WLED_USE_MY_CONFIG | ||||
| @@ -599,13 +599,6 @@ WLED_GLOBAL bool doInitBusses _INIT(false); | ||||
| // Usermod manager | ||||
| WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager()); | ||||
|  | ||||
| // Status LED | ||||
| #if STATUSLED | ||||
|   WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); | ||||
|   WLED_GLOBAL unsigned short ledStatusType _INIT(0); // current status type - corresponds to number of blinks per second | ||||
|   WLED_GLOBAL bool ledStatusState _INIT(0); // the current LED state | ||||
| #endif | ||||
|  | ||||
| // enable additional debug output | ||||
| #ifdef WLED_DEBUG | ||||
|   #ifndef ESP8266 | ||||
| @@ -668,6 +661,7 @@ public: | ||||
|  | ||||
|   void beginStrip(); | ||||
|   void handleConnection(); | ||||
|   bool initEthernet(); // result is informational | ||||
|   void initAP(bool resetAP = false); | ||||
|   void initConnection(); | ||||
|   void initInterfaces(); | ||||
|   | ||||
| @@ -2,7 +2,32 @@ | ||||
| #define WLED_ETHERNET_H | ||||
|  | ||||
| #ifdef WLED_USE_ETHERNET | ||||
| // settings for various ethernet boards | ||||
| #include "pin_manager.h" | ||||
|  | ||||
| // The following six pins are neither configurable nor | ||||
| // can they be re-assigned through IOMUX / GPIO matrix. | ||||
| // See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-ethernet-kit-v1.1.html#ip101gri-phy-interface | ||||
| const managed_pin_type esp32_nonconfigurable_ethernet_pins[6] = { | ||||
|     { 21, true  }, // RMII EMAC TX EN  == When high, clocks the data on TXD0 and TXD1 to transmitter | ||||
|     { 19, true  }, // RMII EMAC TXD0   == First bit of transmitted data | ||||
|     { 22, true  }, // RMII EMAC TXD1   == Second bit of transmitted data | ||||
|     { 25, false }, // RMII EMAC RXD0   == First bit of received data | ||||
|     { 26, false }, // RMII EMAC RXD1   == Second bit of received data | ||||
|     { 27, true  }, // RMII EMAC CRS_DV == Carrier Sense and RX Data Valid | ||||
| }; | ||||
|  | ||||
| // For ESP32, the remaining five pins are at least somewhat configurable. | ||||
| // eth_address  is in range [0..31], indicates which PHY (MAC?) address should be allocated to the interface | ||||
| // eth_power    is an output GPIO pin used to enable/disable the ethernet port (and/or external oscillator) | ||||
| // eth_mdc      is an output GPIO pin used to provide the clock for the management data | ||||
| // eth_mdio     is an input/output GPIO pin used to transfer management data | ||||
| // eth_type     is the physical ethernet module's type (ETH_PHY_LAN8720, ETH_PHY_TLK110) | ||||
| // eth_clk_mode defines the GPIO pin and GPIO mode for the clock signal | ||||
| //              However, there are really only four configurable options on ESP32: | ||||
| //              ETH_CLOCK_GPIO0_IN    == External oscillator, clock input  via GPIO0 | ||||
| //              ETH_CLOCK_GPIO0_OUT   == ESP32 provides 50MHz clock output via GPIO0 | ||||
| //              ETH_CLOCK_GPIO16_OUT  == ESP32 provides 50MHz clock output via GPIO16 | ||||
| //              ETH_CLOCK_GPIO17_OUT  == ESP32 provides 50MHz clock output via GPIO17 | ||||
| typedef struct EthernetSettings { | ||||
|   uint8_t        eth_address; | ||||
|   int            eth_power; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Blaž Kristan
					Blaž Kristan