Skip to content

Prevent immediate deep-sleep wake by draining TCA8418 key FIFO before sleep - #1

Merged
TheCodingSoldier merged 2 commits into
mainfrom
copilot/fix-sleep-issue-271
Aug 18, 2026
Merged

Prevent immediate deep-sleep wake by draining TCA8418 key FIFO before sleep#1
TheCodingSoldier merged 2 commits into
mainfrom
copilot/fix-sleep-issue-271

Conversation

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown

Typing sleep from Home could put the device into deep sleep and then wake it again within seconds. Root cause was pending TCA8418 key events (including Enter) holding KB_IRQ low, which is also the ESP32-S3 deep-sleep wake source.

  • Sleep-path hardening in UTILS.cpp

    • Added FIFO drain immediately before pocketmage::deepSleep() in PWR_BTN_event sleep handlers.
    • Applied to both build paths (OTA_APP and OS app) where power-event sleep is dispatched.
  • IRQ deassert stabilization

    • Added a short delay(50) after draining key events to allow KB_IRQ to return high before entering deep sleep.
  • Behavioral impact

    • Preserves existing sleep flow and state handling; only inserts pre-sleep keyboard IRQ cleanup to prevent false wake triggers from queued keypresses.
if (PWR_BTN_event && CurrentHOMEState != NOWLATER) {
  PWR_BTN_event = false;
  ESP_LOGE(TAG, "Power Button Event: Sleeping now");
  while (KB().updateKeypress() != 0) {}
  delay(50);
  pocketmage::deepSleep();
}
Original prompt

Fix TailsmanDesign#271: PM waking up after "sleep" command is entered

Bug Description

When the user types "sleep" on the home screen and presses Enter, the device goes to sleep but wakes up again after ~5 seconds. Confirmed still broken as of Aug 17, 2026.

Issue: TailsmanDesign#271

Root Cause

The ESP32-S3 uses the TCA8418 keyboard controller's IRQ pin (KB_IRQ, GPIO 8, defined in Code/PocketMageOS/include/config.h) as the deep sleep wake source:

esp_sleep_enable_ext0_wakeup((gpio_num_t)KB_IRQ, 0);  // in pocketmage_sys.cpp

The TCA8418 asserts IRQ LOW when there are pending key events in its FIFO.

When the "sleep" command is processed:

  1. Code/PocketMageOS/src/OS_APPS/HOME.cpp sets PWR_BTN_event = true (the direct deepSleep() call is commented out)
  2. Code/PocketMageOS/src/UTILS.cpp checks the flag: if (PWR_BTN_event && CurrentHOMEState != NOWLATER) { PWR_BTN_event = false; pocketmage::deepSleep(); }
  3. pocketmage_sys.cpp's deepSleep() calls esp_deep_sleep_start()

But the TCA8418 FIFO still contains pending key events (the Enter keypress that submitted the "sleep" command). The KB_IRQ pin stays LOW, so the ESP32 wakes immediately after entering deep sleep.

Collaborator ashtf8 suggested: "I think this could be fixed by clearing the keyboard buffer after that command..."

Fix

In Code/PocketMageOS/src/UTILS.cpp, in the PWR_BTN_event handler block, BEFORE calling pocketmage::deepSleep(), drain the TCA8418 keyboard FIFO by calling KB().updateKeypress() in a loop until it returns 0, then add a small delay (~50ms) to let the KB_IRQ pin deassert.

Current code (in UTILS.cpp, approximately):

if (PWR_BTN_event && CurrentHOMEState != NOWLATER) {
    PWR_BTN_event = false;
    ESP_LOGE(TAG, "Power Button Event: Sleeping now");
    pocketmage::deepSleep();

Should become:

if (PWR_BTN_event && CurrentHOMEState != NOWLATER) {
    PWR_BTN_event = false;
    ESP_LOGE(TAG, "Power Button Event: Sleeping now");
    // Fix #271: Drain TCA8418 keyboard FIFO before sleep to prevent
    // pending key events from keeping KB_IRQ LOW and causing immediate wake
    while (KB().updateKeypress() != 0) { /* discard pending keys */ }
    delay(50);
    pocketmage::deepSleep();

API Reference

  • KB() returns the PocketmageKB singleton (declared in Code/PocketMageOS/lib/PocketMage/pocketmage_kb/pocketmage_kb.h)
  • KB().updateKeypress() pulls one key from the TCA8418 FIFO and returns 0 when empty (already used throughout the codebase: JOURNAL.cpp, USB.cpp, COMM.cpp, etc.)
  • KB() is already used in UTILS.cpp (e.g., KB().setKeyboardState(NORMAL), KB().updateKeypress())
  • KB_IRQ is GPIO 8 (defined in config.h)
  • The wake source is set up in pocketmage_sys.cpp

Testing

Build with PlatformIO (PM_PRODUCTION config). No local unit test harness exists. Hardware testing needed before merge (same pattern as PRs TailsmanDesign#297/TailsmanDesign#301/TailsmanDesign#319).

Co-authored-by: TheCodingSoldier <257933801+TheCodingSoldier@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix PM waking up after 'sleep' command is entered Prevent immediate deep-sleep wake by draining TCA8418 key FIFO before sleep Aug 18, 2026
Copilot AI requested a review from TheCodingSoldier August 18, 2026 01:22
@TheCodingSoldier
TheCodingSoldier marked this pull request as ready for review August 18, 2026 01:26
Copilot AI lite review requested due to automatic review settings August 18, 2026 01:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@TheCodingSoldier
TheCodingSoldier merged commit 83298a2 into main Aug 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PM waking up after "sleep" command is entered

3 participants