Refactor main loop touch flow and update docs
This commit is contained in:
39
basic1.cpp
39
basic1.cpp
@@ -14,7 +14,7 @@
|
||||
* - Event-driven: Display only updates when input is received
|
||||
* - Power efficient: Uses __wfi() to sleep between inputs
|
||||
* - E-ink optimized: Minimizes screen refreshes
|
||||
* - Interrupt-driven: Touch and button handling via interrupts
|
||||
* - Hybrid input handling: IRQ wake-up plus active-touch sampling
|
||||
* - Modular: Clear separation of input, game logic, and rendering
|
||||
*
|
||||
* ARCHITECTURE:
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "board_config.h" // Board-specific pin configuration
|
||||
#include "sd_card.h"
|
||||
@@ -171,7 +170,6 @@ static uint32_t last_interaction_time = 0; // Last time user interacted
|
||||
static bool is_idle_2min_triggered = false; // Flag for 2min trigger
|
||||
static bool is_idle_10min_triggered = false; // Flag for 10min trigger
|
||||
static volatile bool dim_check_flag = false; // Flag set by timer to check dimming
|
||||
static LowLevelDisplay* global_display = nullptr; // Global display pointer for timer callback
|
||||
|
||||
/**
|
||||
* @brief Update last interaction time and notify display driver
|
||||
@@ -269,6 +267,18 @@ static inline bool has_pending_wake_source() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true when the currently selected game needs frame ticks.
|
||||
*/
|
||||
static inline bool game_wants_frame_updates(GameLauncher& launcher) {
|
||||
if (!launcher.is_game_selected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Game* game = launcher.get_selected_game();
|
||||
return game && game->wants_frame_updates();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Touch interrupt callback handler
|
||||
*
|
||||
@@ -282,6 +292,8 @@ static inline bool has_pending_wake_source() {
|
||||
* @param events Event mask (GPIO_IRQ_EDGE_FALL and/or GPIO_IRQ_EDGE_RISE)
|
||||
*/
|
||||
void touch_interrupt_handler(uint gpio, uint32_t events) {
|
||||
(void)gpio;
|
||||
|
||||
// Track which edge triggered (down vs up).
|
||||
// Keep ISR minimal: do not log/print from interrupt context.
|
||||
if (events & GPIO_IRQ_EDGE_FALL) {
|
||||
@@ -325,9 +337,6 @@ void button_interrupt_handler(uint gpio, uint32_t events) {
|
||||
const int V_WIDTH = DISPLAY_WIDTH;
|
||||
const int V_HEIGHT = DISPLAY_HEIGHT;
|
||||
|
||||
// Touch indicator settings
|
||||
#define TOUCH_RADIUS 10
|
||||
|
||||
uint8_t bit_buffer[V_WIDTH * V_HEIGHT / 8];
|
||||
|
||||
/**
|
||||
@@ -427,7 +436,7 @@ int main()
|
||||
if (touch) {
|
||||
printf("Touch initialized successfully\n");
|
||||
|
||||
// Set up interrupt-driven touch detection
|
||||
// Set up touch IRQ wake-up (InputManager handles active-touch sampling)
|
||||
printf("Setting up touch interrupt callback...\n");
|
||||
touch->set_interrupt_callback(touch_interrupt_handler);
|
||||
printf("Touch interrupt enabled on INT pin (falling and rising edges)\n");
|
||||
@@ -549,10 +558,11 @@ int main()
|
||||
// Core 0 (this loop): Handles input and game logic - stays responsive
|
||||
// Core 1: Handles display refresh - can take 1-2 seconds for e-ink
|
||||
//
|
||||
// The loop sleeps until an interrupt occurs, then:
|
||||
// The loop primarily sleeps on __wfi(), and wakes to:
|
||||
// 1. Process input (button or touch)
|
||||
// 2. Update game state based on input
|
||||
// 3. Queue refresh on Core 1 (non-blocking)
|
||||
// While touch is active or a game needs frame ticks, the loop stays awake.
|
||||
// This keeps Core 0 responsive even during slow e-ink refreshes
|
||||
// ========================================================================
|
||||
|
||||
@@ -561,8 +571,6 @@ int main()
|
||||
|
||||
// Initialize last interaction time to current time
|
||||
last_interaction_time = to_ms_since_boot(get_absolute_time());
|
||||
global_display = display;
|
||||
|
||||
// Set up repeating alarm to periodically check dimming status
|
||||
// This wakes the CPU from __wfi() every DIM_CHECK_INTERVAL_MS
|
||||
add_alarm_in_ms(DIM_CHECK_INTERVAL_MS, dim_check_alarm_callback, nullptr, true);
|
||||
@@ -612,12 +620,7 @@ int main()
|
||||
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();
|
||||
if (g && g->wants_frame_updates()) {
|
||||
stay_awake = true;
|
||||
}
|
||||
}
|
||||
if (game_wants_frame_updates(launcher)) stay_awake = true;
|
||||
|
||||
if (!stay_awake) {
|
||||
// Sleep until interrupt wakes us up (very power efficient!)
|
||||
@@ -722,10 +725,10 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
if (launcher.is_game_selected()) {
|
||||
if (game_wants_frame_updates(launcher)) {
|
||||
// No input, but check if game wants continuous updates
|
||||
current_game = launcher.get_selected_game();
|
||||
if (current_game->wants_frame_updates()) {
|
||||
if (current_game) {
|
||||
// Only send frame tick if we're ready to draw the next frame
|
||||
if (!is_refresh_in_progress()) {
|
||||
InputEvent frame_tick = {INPUT_FRAME_TICK, 0, 0, 0, 0, 0, true};
|
||||
|
||||
Reference in New Issue
Block a user