Fix touch event stability and WFI wake filtering
This commit is contained in:
40
basic1.cpp
40
basic1.cpp
@@ -252,6 +252,23 @@ volatile bool button_key0_pressed = false;
|
|||||||
volatile bool button_key1_pressed = false;
|
volatile bool button_key1_pressed = false;
|
||||||
#endif
|
#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
|
* @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)
|
* @param events Event mask (GPIO_IRQ_EDGE_FALL and/or GPIO_IRQ_EDGE_RISE)
|
||||||
*/
|
*/
|
||||||
void touch_interrupt_handler(uint gpio, uint32_t events) {
|
void touch_interrupt_handler(uint gpio, uint32_t events) {
|
||||||
// Set flag to indicate touch event occurred
|
// Track which edge triggered (down vs up).
|
||||||
// Main loop will handle the actual touch reading
|
// Keep ISR minimal: do not log/print from interrupt context.
|
||||||
touch_interrupt_flag = true;
|
if (events & GPIO_IRQ_EDGE_FALL) {
|
||||||
|
|
||||||
// Track which edge triggered (down vs up)
|
|
||||||
if (events & GPIO_IRQ_EDGE_FALL) {
|
|
||||||
touch_event_down = true;
|
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;
|
touch_event_down = false;
|
||||||
printf("INT: RISE\n");
|
touch_interrupt_flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,6 +609,8 @@ int main()
|
|||||||
bool stay_awake = false;
|
bool stay_awake = false;
|
||||||
if (pending_refresh) stay_awake = true;
|
if (pending_refresh) stay_awake = true;
|
||||||
if (serial_uploader.wants_to_launch_game()) stay_awake = true; // Don't sleep while waiting to launch
|
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()) {
|
if (launcher.is_game_selected()) {
|
||||||
Game* g = launcher.get_selected_game();
|
Game* g = launcher.get_selected_game();
|
||||||
@@ -606,6 +622,12 @@ int main()
|
|||||||
if (!stay_awake) {
|
if (!stay_awake) {
|
||||||
// Sleep until interrupt wakes us up (very power efficient!)
|
// Sleep until interrupt wakes us up (very power efficient!)
|
||||||
__wfi(); // Wait For Interrupt - CPU sleeps until any interrupt occurs
|
__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};
|
InputEvent input = {INPUT_NONE, 0, 0, 0, 0, 0, false};
|
||||||
|
|||||||
@@ -143,11 +143,6 @@ bool ft6336u_init(const ft6336u_config_t *config) {
|
|||||||
printf("[FT6336U] WARNING: Failed to set CTRL mode\n");
|
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
|
// Configure gesture parameters for better detection
|
||||||
printf("[FT6336U] Configuring gesture detection parameters...\n");
|
printf("[FT6336U] Configuring gesture detection parameters...\n");
|
||||||
|
|||||||
@@ -42,77 +42,73 @@ bool InputManager::has_buttons() const {
|
|||||||
InputEvent InputManager::process_touch_input(uint32_t* last_time) {
|
InputEvent InputManager::process_touch_input(uint32_t* last_time) {
|
||||||
InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false};
|
InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false};
|
||||||
|
|
||||||
// Check if touch interrupt flag is set
|
// Process immediately on IRQ, and continue sampling while a touch is active.
|
||||||
if (!touch_interrupt_flag) {
|
// Some controllers only IRQ on edge transitions, so move events require polling.
|
||||||
|
if (!touch_interrupt_flag && *last_time == 0) {
|
||||||
return event; // No touch event
|
return event; // No touch event
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Processing touch: flag=%d, event_down=%d\n", touch_interrupt_flag, touch_event_down);
|
// Always validate via controller state instead of relying on edge flag alone.
|
||||||
|
// Edge chatter can flip touch_event_down without a real touch transition.
|
||||||
// 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
|
|
||||||
TouchData touch_data;
|
TouchData touch_data;
|
||||||
if (!touch || !touch->read_touch(&touch_data)) {
|
if (!touch || !touch->read_touch(&touch_data)) {
|
||||||
// Clear flag even if read failed to prevent getting stuck
|
|
||||||
touch_interrupt_flag = false;
|
touch_interrupt_flag = false;
|
||||||
printf("Touch read FAILED\n");
|
return event;
|
||||||
return event; // Read failed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the interrupt flag after successfully reading touch data
|
|
||||||
// This allows the next touch interrupt to be detected
|
|
||||||
touch_interrupt_flag = false;
|
touch_interrupt_flag = false;
|
||||||
|
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||||
printf("Touch DOWN at (%d,%d)\n", touch_data.points[0].x, touch_data.points[0].y);
|
|
||||||
|
// No active touch points: require consecutive empty reads before release to
|
||||||
// Populate event structure
|
// 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.x = touch_data.points[0].x;
|
||||||
event.y = touch_data.points[0].y;
|
event.y = touch_data.points[0].y;
|
||||||
event.pressure = touch_data.points[0].pressure;
|
event.pressure = touch_data.points[0].pressure;
|
||||||
event.gesture_code = touch_data.gesture;
|
event.gesture_code = touch_data.gesture;
|
||||||
event.valid = true;
|
event.valid = true;
|
||||||
|
|
||||||
// Determine event type
|
|
||||||
if (*last_time == 0) {
|
if (*last_time == 0) {
|
||||||
event.type = INPUT_TOUCH_DOWN;
|
event.type = INPUT_TOUCH_DOWN;
|
||||||
|
|
||||||
// Check for virtual buttons
|
|
||||||
InputType virtual_type;
|
InputType virtual_type;
|
||||||
if (check_virtual_buttons(event.x, event.y, virtual_type)) {
|
if (check_virtual_buttons(event.x, event.y, virtual_type)) {
|
||||||
event.type = virtual_type;
|
event.type = virtual_type;
|
||||||
event.button_id = (virtual_type == INPUT_BUTTON_0) ? 0 : 1;
|
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 {
|
} else {
|
||||||
event.type = INPUT_TOUCH_MOVE;
|
event.type = INPUT_TOUCH_MOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle gesture events
|
|
||||||
if (config->enable_gestures && touch_data.gesture != 0) {
|
if (config->enable_gestures && touch_data.gesture != 0) {
|
||||||
event.type = INPUT_GESTURE;
|
event.type = INPUT_GESTURE;
|
||||||
if (config->debug_verbose) {
|
if (config->debug_verbose) {
|
||||||
printf("Gesture: 0x%02X (%s)\n", event.gesture_code, get_gesture_name(event.gesture_code));
|
printf("Gesture: 0x%02X (%s)\n", event.gesture_code, get_gesture_name(event.gesture_code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*last_time = now;
|
*last_time = now;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
LowLevelTouch* touch;
|
LowLevelTouch* touch;
|
||||||
const GameConfig* config;
|
const GameConfig* config;
|
||||||
|
uint8_t no_touch_samples = 0;
|
||||||
|
|
||||||
// Virtual button regions
|
// Virtual button regions
|
||||||
int v_button_a[4] = {0, 0, 0, 0}; // [x, y, w, h]
|
int v_button_a[4] = {0, 0, 0, 0}; // [x, y, w, h]
|
||||||
|
|||||||
Reference in New Issue
Block a user