From fe6e403a9836e131d00cd7e3ac677006e83519a5 Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Wed, 18 Feb 2026 15:53:48 -0500 Subject: [PATCH] Reduce touch overhead and cap frame rate at 24 FPS --- basic1.cpp | 8 ++++---- lib/ft6336u/ft6336u.c | 10 ++++++---- lib/input_manager.cpp | 15 ++++++++++++++- lib/input_manager.h | 2 ++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/basic1.cpp b/basic1.cpp index 03cbc43..e22d135 100644 --- a/basic1.cpp +++ b/basic1.cpp @@ -722,13 +722,13 @@ int main() printf("\nEntering reactive game loop (Core 0 - input & logic)\n"); printf("Display refreshes handled by Core 1\n"); - printf("Frame rate limited to 30 FPS (33.3ms per frame)\n\n"); + printf("Frame rate limited to 24 FPS (41.7ms per frame)\n\n"); Game* current_game = nullptr; uint32_t game_start_time = 0; - // Frame rate limiting (30 FPS = 33.33ms per frame) - const uint32_t TARGET_FRAME_TIME_MS = 33; // 1000ms / 30fps ≈ 33ms + // Frame rate limiting (24 FPS = 41.67ms per frame) + const uint32_t TARGET_FRAME_TIME_MS = 42; // 1000ms / 24fps ≈ 41.7ms uint32_t last_frame_time = 0; bool needs_refresh = false; // Track if screen needs redraw @@ -990,7 +990,7 @@ int main() } } - // 4. Redraw and queue async refresh on Core 1 (with 30 FPS limiting) + // 4. Redraw and queue async refresh on Core 1 (with 24 FPS limiting) if (needs_refresh || pending_refresh) { // Check frame rate limiting uint32_t current_time = to_ms_since_boot(get_absolute_time()); diff --git a/lib/ft6336u/ft6336u.c b/lib/ft6336u/ft6336u.c index 1a1023c..4faf889 100644 --- a/lib/ft6336u/ft6336u.c +++ b/lib/ft6336u/ft6336u.c @@ -27,8 +27,9 @@ static bool ft6336u_read_reg(uint8_t reg, uint8_t *value) { continue; } - // Add delay after write, before read (like Arduino library does) - sleep_us(10000); // 10ms delay + // Short settle time between register address write and read. + // 10ms here heavily throttles touch sampling during hold/move. + sleep_us(100); // 0.1ms result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, value, 1, false); if (result == 1) { @@ -50,8 +51,9 @@ static bool ft6336u_read_regs(uint8_t reg, uint8_t *buf, size_t len) { continue; } - // Add delay after write, before read (like Arduino library does) - sleep_us(10000); // 10ms delay + // Short settle time between register address write and read. + // 10ms here heavily throttles touch sampling during hold/move. + sleep_us(100); // 0.1ms result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, buf, len, false); if (result == (int)len) { diff --git a/lib/input_manager.cpp b/lib/input_manager.cpp index 04e576e..3216db7 100644 --- a/lib/input_manager.cpp +++ b/lib/input_manager.cpp @@ -40,6 +40,8 @@ bool InputManager::has_buttons() const { InputEvent InputManager::process_touch_input(uint32_t* last_time) { InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false}; + const uint32_t now = to_ms_since_boot(get_absolute_time()); + static constexpr uint32_t ACTIVE_TOUCH_SAMPLE_INTERVAL_MS = 8; // Process immediately on IRQ, and continue sampling while a touch is active. // Some controllers only IRQ on edge transitions, so move events require polling. @@ -47,16 +49,26 @@ InputEvent InputManager::process_touch_input(uint32_t* last_time) { return event; // No touch event } + // While a touch session is active, avoid reading touch hardware every loop + // iteration. IRQ edges (down/up) still bypass this throttle for responsiveness. + if (!touch_interrupt_flag && *last_time != 0) { + uint32_t elapsed = now - last_touch_sample_ms; + if (elapsed < ACTIVE_TOUCH_SAMPLE_INTERVAL_MS) { + return event; + } + } + // 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)) { + last_touch_sample_ms = now; touch_interrupt_flag = false; return event; } + last_touch_sample_ms = now; touch_interrupt_flag = false; - 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. @@ -65,6 +77,7 @@ InputEvent InputManager::process_touch_input(uint32_t* last_time) { no_touch_samples++; if (no_touch_samples >= 2) { *last_time = 0; + last_touch_sample_ms = 0; no_touch_samples = 0; event.type = INPUT_TOUCH_UP; event.valid = true; diff --git a/lib/input_manager.h b/lib/input_manager.h index 68137cd..b78cdda 100644 --- a/lib/input_manager.h +++ b/lib/input_manager.h @@ -97,6 +97,8 @@ public: private: LowLevelTouch* touch; const GameConfig* config; + // Last time we sampled touch over I2C while a touch session is active. + uint32_t last_touch_sample_ms = 0; // Consecutive touch_count==0 samples while a touch session is active. // Used to suppress false TOUCH_UP events from transient touch controller jitter. uint8_t no_touch_samples = 0;