diff --git a/src/input/TCA8418KeyboardBase.cpp b/src/input/TCA8418KeyboardBase.cpp index 1abd05e36..a5ecbd0a0 100644 --- a/src/input/TCA8418KeyboardBase.cpp +++ b/src/input/TCA8418KeyboardBase.cpp @@ -2,6 +2,7 @@ #include "TCA8418KeyboardBase.h" #include "configuration.h" +#include "sleep.h" #include @@ -44,14 +45,18 @@ void TCA8418KeyboardBase::begin(uint8_t addr, TwoWire *wire) reset(); #ifdef KB_INT - interruptInstance = this; - auto interruptHandler = []() { interruptInstance->notifyObservers(interruptInstance); }; - ::pinMode(KB_INT, INPUT_PULLUP); - attachInterrupt(KB_INT, interruptHandler, FALLING); - + attachInterruptHandler(); enableInterrupts(); -#endif + +#ifdef ARCH_ESP32 + // Register callbacks for before and after lightsleep + // Used to detach and reattach interrupts + lsObserver.observe(¬ifyLightSleep); + lsEndObserver.observe(¬ifyLightSleepEnd); +#endif // ARCH_ESP32 + +#endif // KB_INT } void TCA8418KeyboardBase::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr) @@ -93,6 +98,41 @@ void TCA8418KeyboardBase::reset() flush(); } +#ifdef KB_INT +void TCA8418KeyboardBase::attachInterruptHandler() +{ + interruptInstance = this; + auto interruptHandler = []() { interruptInstance->notifyObservers(interruptInstance); }; + attachInterrupt(KB_INT, interruptHandler, FALLING); +} + +void TCA8418KeyboardBase::detachInterruptHandler() +{ + detachInterrupt(KB_INT); + interruptInstance = nullptr; +} + +#ifdef ARCH_ESP32 +// Detach our class' interrupts before lightsleep +// Allows sleep.cpp to configure its own interrupts, which wake the device on user-button press +int TCA8418KeyboardBase::beforeLightSleep(void *unused) +{ + detachInterruptHandler(); + return 0; // Indicates success +} + +// Reconfigure our interrupts +// Our class' interrupts were disconnected during sleep, to allow the user button to wake the device from sleep +int TCA8418KeyboardBase::afterLightSleep(esp_sleep_wakeup_cause_t cause) +{ + attachInterruptHandler(); + this->notifyObservers(this); // Trigger a one-off poll in case a keypress woke us + return 0; // Indicates success +} +#endif // ARCH_ESP32 + +#endif // KB_INT + bool TCA8418KeyboardBase::matrix(uint8_t rows, uint8_t columns) { if (rows < 1 || rows > 8 || columns < 1 || columns > 10) @@ -169,7 +209,7 @@ void TCA8418KeyboardBase::trigger() #ifdef KB_INT // Reset interrupt mask so we can receive future interrupts - writeRegister(TCA8418_REG_INT_STAT, 3); + clearInt(); #endif } diff --git a/src/input/TCA8418KeyboardBase.h b/src/input/TCA8418KeyboardBase.h index 9f68bc885..0321ffe70 100644 --- a/src/input/TCA8418KeyboardBase.h +++ b/src/input/TCA8418KeyboardBase.h @@ -163,9 +163,29 @@ class TCA8418KeyboardBase : public KbInterruptObservable uint8_t columns; String queue; +#ifdef KB_INT + void attachInterruptHandler(); + void detachInterruptHandler(); + +#ifdef ARCH_ESP32 + // Disconnect and reconnect interrupts for light sleep + int beforeLightSleep(void *unused); + int afterLightSleep(esp_sleep_wakeup_cause_t cause); +#endif // ARCH_ESP32 + +#endif // KB_INT + private: TwoWire *m_wire; uint8_t m_addr; i2c_com_fptr_t readCallback; i2c_com_fptr_t writeCallback; + +#if defined(KB_INT) && defined(ARCH_ESP32) + // Get notified when lightsleep begins and ends + CallbackObserver lsObserver = + CallbackObserver(this, &TCA8418KeyboardBase::beforeLightSleep); + CallbackObserver lsEndObserver = + CallbackObserver(this, &TCA8418KeyboardBase::afterLightSleep); +#endif }; diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index 5202f5b71..dbc1f713f 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -441,7 +441,6 @@ int32_t KbI2cBase::runOnce() this->notifyObservers(&e); } } - TCAKeyboard.clearInt(); #endif break; }