diff --git a/basic1.cpp b/basic1.cpp index 4538047..455bde6 100644 --- a/basic1.cpp +++ b/basic1.cpp @@ -252,6 +252,23 @@ volatile bool button_key0_pressed = false; volatile bool button_key1_pressed = false; #endif +/** + * @brief Returns true when an application-level wake source is pending. + * + * __wfi() can wake on unrelated interrupts (e.g. USB/background IRQs). This + * guard prevents running full input/game logic unless one of our expected + * event sources actually fired. + */ +static inline bool has_pending_wake_source() { + if (touch_interrupt_flag) return true; + if (touch_event_down) return true; + if (dim_check_flag) return true; +#ifdef BUTTON_KEY0_PIN + if (button_key0_pressed || button_key1_pressed) return true; +#endif + return false; +} + /** * @brief Touch interrupt callback handler * @@ -265,18 +282,15 @@ volatile bool button_key1_pressed = false; * @param events Event mask (GPIO_IRQ_EDGE_FALL and/or GPIO_IRQ_EDGE_RISE) */ void touch_interrupt_handler(uint gpio, uint32_t events) { - // Set flag to indicate touch event occurred - // Main loop will handle the actual touch reading - touch_interrupt_flag = true; - - // Track which edge triggered (down vs up) - if (events & GPIO_IRQ_EDGE_FALL) { + // Track which edge triggered (down vs up). + // Keep ISR minimal: do not log/print from interrupt context. + if (events & GPIO_IRQ_EDGE_FALL) { touch_event_down = true; - printf("INT: FALL\n"); + touch_interrupt_flag = true; } - if (events & GPIO_IRQ_EDGE_RISE) { + if (events & GPIO_IRQ_EDGE_RISE) { touch_event_down = false; - printf("INT: RISE\n"); + touch_interrupt_flag = true; } } @@ -595,6 +609,8 @@ int main() bool stay_awake = false; if (pending_refresh) stay_awake = true; if (serial_uploader.wants_to_launch_game()) stay_awake = true; // Don't sleep while waiting to launch + if (touch_event_down) stay_awake = true; // Keep sampling while finger is down + if (last_touch_time != 0) stay_awake = true; // Keep sampling during active touch session if (launcher.is_game_selected()) { Game* g = launcher.get_selected_game(); @@ -606,6 +622,12 @@ int main() if (!stay_awake) { // Sleep until interrupt wakes us up (very power efficient!) __wfi(); // Wait For Interrupt - CPU sleeps until any interrupt occurs + + // Ignore unrelated interrupts (USB/background/timer noise). + // Only continue loop work when one of our wake sources is pending. + if (!has_pending_wake_source()) { + continue; + } } InputEvent input = {INPUT_NONE, 0, 0, 0, 0, 0, false}; diff --git a/lib/ft6336u/ft6336u.c b/lib/ft6336u/ft6336u.c index acd6c56..1a1023c 100644 --- a/lib/ft6336u/ft6336u.c +++ b/lib/ft6336u/ft6336u.c @@ -143,11 +143,6 @@ bool ft6336u_init(const ft6336u_config_t *config) { printf("[FT6336U] WARNING: Failed to set CTRL mode\n"); } - // Enable polling mode - INT pin stays LOW while touched, goes HIGH when released - printf("[FT6336U] Enabling polling mode...\n"); - if (!ft6336u_write_reg(FT6336U_REG_G_MODE, FT6336U_G_MODE_POLLING)) { - printf("[FT6336U] WARNING: Failed to set G_MODE\n"); - } // Configure gesture parameters for better detection printf("[FT6336U] Configuring gesture detection parameters...\n"); diff --git a/lib/input_manager.cpp b/lib/input_manager.cpp index 7f61047..e5f0781 100644 --- a/lib/input_manager.cpp +++ b/lib/input_manager.cpp @@ -42,77 +42,73 @@ bool InputManager::has_buttons() const { InputEvent InputManager::process_touch_input(uint32_t* last_time) { InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false}; - // Check if touch interrupt flag is set - if (!touch_interrupt_flag) { + // Process immediately on IRQ, and continue sampling while a touch is active. + // Some controllers only IRQ on edge transitions, so move events require polling. + if (!touch_interrupt_flag && *last_time == 0) { return event; // No touch event } - - printf("Processing touch: flag=%d, event_down=%d\n", touch_interrupt_flag, touch_event_down); - - // Don't clear the flag yet - we may still be processing continuous touch - - // Check if touch is active - if (!touch_event_down) { - // Touch released - reset timing for next touch - touch_interrupt_flag = false; - *last_time = 0; // Reset so next touch is treated as new touch-down - event.type = INPUT_TOUCH_UP; - event.valid = true; - printf("Touch UP\n"); - return event; - } - - // Touch is down - check debounce timing - uint32_t now = to_ms_since_boot(get_absolute_time()); - if (now - *last_time < config->touch_debounce_ms) { - return event; // Too soon, skip - } - - // Read touch data + + // Always validate via controller state instead of relying on edge flag alone. + // Edge chatter can flip touch_event_down without a real touch transition. TouchData touch_data; if (!touch || !touch->read_touch(&touch_data)) { - // Clear flag even if read failed to prevent getting stuck touch_interrupt_flag = false; - printf("Touch read FAILED\n"); - return event; // Read failed + return event; } - - // Clear the interrupt flag after successfully reading touch data - // This allows the next touch interrupt to be detected + touch_interrupt_flag = false; - - printf("Touch DOWN at (%d,%d)\n", touch_data.points[0].x, touch_data.points[0].y); - - // Populate event structure + uint32_t now = to_ms_since_boot(get_absolute_time()); + + // No active touch points: require consecutive empty reads before release to + // avoid false TOUCH_UP events from transient controller jitter. + if (touch_data.touch_count == 0) { + if (*last_time != 0) { + no_touch_samples++; + if (no_touch_samples >= 2) { + *last_time = 0; + no_touch_samples = 0; + event.type = INPUT_TOUCH_UP; + event.valid = true; + } + } + return event; + } + no_touch_samples = 0; + + // Debounce touch-down/move updates. + if (*last_time != 0 && (now - *last_time) < config->touch_debounce_ms) { + return event; + } + + // Populate event from first touch point. event.x = touch_data.points[0].x; event.y = touch_data.points[0].y; event.pressure = touch_data.points[0].pressure; event.gesture_code = touch_data.gesture; event.valid = true; - - // Determine event type + if (*last_time == 0) { event.type = INPUT_TOUCH_DOWN; - // Check for virtual buttons InputType virtual_type; if (check_virtual_buttons(event.x, event.y, virtual_type)) { event.type = virtual_type; event.button_id = (virtual_type == INPUT_BUTTON_0) ? 0 : 1; - printf("Virtual button %d pressed via touch\n", event.button_id); + if (config->debug_verbose) { + printf("Virtual button %d pressed via touch\n", event.button_id); + } } } else { event.type = INPUT_TOUCH_MOVE; } - - // Handle gesture events + if (config->enable_gestures && touch_data.gesture != 0) { event.type = INPUT_GESTURE; if (config->debug_verbose) { printf("Gesture: 0x%02X (%s)\n", event.gesture_code, get_gesture_name(event.gesture_code)); } } - + *last_time = now; return event; } diff --git a/lib/input_manager.h b/lib/input_manager.h index e9f45a4..8215785 100644 --- a/lib/input_manager.h +++ b/lib/input_manager.h @@ -97,6 +97,7 @@ public: private: LowLevelTouch* touch; const GameConfig* config; + uint8_t no_touch_samples = 0; // Virtual button regions int v_button_a[4] = {0, 0, 0, 0}; // [x, y, w, h]