Add auto-sleep/wake functionality with timer-based dimming
- Added PWM brightness control to ST7796 driver (0-100%) - Implemented hardware sleep mode for ST7796 (saves ~150mA) - Added sleep/wake functions preserving framebuffer and settings - Implemented timer-based inactivity detection (checks every 10s) - Auto-sleep after 5 minutes of no user input - Touch controller remains active during TFT sleep for instant wake - E-ink display also sleeps after timeout, requires re-init on wake - Added hardware_pwm library dependency to CMakeLists.txt - Brightness and sleep/wake methods exposed through display abstraction layer
This commit is contained in:
133
basic1.cpp
133
basic1.cpp
@@ -49,6 +49,7 @@ extern "C" {
|
||||
#include "display/low_level_render.h"
|
||||
#include "display/low_level_display.h"
|
||||
#include "display/low_level_display_epaper.h"
|
||||
#include "display/low_level_display_st7796.h"
|
||||
#include "display/low_level_touch.h"
|
||||
#include "input_manager.h"
|
||||
#include "game.h"
|
||||
@@ -151,6 +152,110 @@ struct GameConfig {
|
||||
bool debug_verbose; // Print debug messages
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// DISPLAY DIMMING CONFIGURATION
|
||||
// ============================================================================
|
||||
|
||||
// Display dimming settings
|
||||
#define DIM_TIMEOUT_MS (5 * 60 * 1000) // 5 minutes in milliseconds
|
||||
#define DIM_CHECK_INTERVAL_MS 10000 // Check every 10 seconds
|
||||
#define DIM_BRIGHTNESS 5 // Dimmed brightness level (0-100)
|
||||
#define NORMAL_BRIGHTNESS 100 // Normal brightness level (0-100)
|
||||
|
||||
// Display dimming state
|
||||
static uint32_t last_interaction_time = 0; // Last time user interacted
|
||||
static bool is_dimmed = false; // Current dimming state
|
||||
static uint8_t saved_brightness = NORMAL_BRIGHTNESS; // Brightness before dimming
|
||||
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 restore display if dimmed
|
||||
*
|
||||
* Call this whenever the user interacts with the device (touch, button press)
|
||||
* to reset the dimming timer and restore display if it was dimmed/sleeping.
|
||||
*
|
||||
* For TFT displays: Restores brightness level
|
||||
* For e-ink displays: Wakes display from sleep and refreshes screen
|
||||
*
|
||||
* @param display Pointer to display interface
|
||||
*/
|
||||
static inline void record_user_interaction(LowLevelDisplay* display) {
|
||||
last_interaction_time = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
// If display was dimmed, restore it based on display type
|
||||
if (is_dimmed) {
|
||||
if (display->get_type() == DISPLAY_TYPE_ST7796) {
|
||||
// TFT: Wake from sleep mode (touch was always active)
|
||||
LowLevelDisplayST7796* tft = static_cast<LowLevelDisplayST7796*>(display);
|
||||
tft->wake();
|
||||
printf("TFT display woken from sleep\n");
|
||||
} else if (display->get_type() == DISPLAY_TYPE_EPAPER) {
|
||||
// E-ink: Wake from sleep and re-initialize
|
||||
printf("Waking e-paper display from sleep...\n");
|
||||
LowLevelDisplayEPaper* epaper = static_cast<LowLevelDisplayEPaper*>(display);
|
||||
epaper->init(); // Re-initialize after sleep
|
||||
printf("E-paper display ready\n");
|
||||
}
|
||||
is_dimmed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Timer callback to periodically check dimming status
|
||||
*
|
||||
* This alarm callback fires every DIM_CHECK_INTERVAL_MS milliseconds
|
||||
* to wake the CPU from __wfi() and check if dimming should occur.
|
||||
* Running in interrupt context, so just sets a flag for main loop.
|
||||
*
|
||||
* @param id Alarm ID (unused)
|
||||
* @param user_data User data pointer (unused)
|
||||
* @return Next alarm time (relative to current time)
|
||||
*/
|
||||
static int64_t dim_check_alarm_callback(alarm_id_t id, void *user_data) {
|
||||
// Set flag to check dimming in main loop
|
||||
dim_check_flag = true;
|
||||
|
||||
// Return interval in microseconds for next alarm
|
||||
// Negative value means schedule relative to now
|
||||
return -(DIM_CHECK_INTERVAL_MS * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if display should be dimmed and apply dimming if needed
|
||||
*
|
||||
* Checks if the timeout has elapsed since last interaction and dims/sleeps
|
||||
* the display based on its type:
|
||||
* - TFT displays (ST7796): Reduces brightness to minimum
|
||||
* - E-ink displays: Puts display to sleep mode (turns off)
|
||||
*
|
||||
* @param display Pointer to display interface
|
||||
*/
|
||||
static inline void check_and_apply_dimming(LowLevelDisplay* display) {
|
||||
uint32_t current_time = to_ms_since_boot(get_absolute_time());
|
||||
uint32_t elapsed = current_time - last_interaction_time;
|
||||
|
||||
// Check if timeout has elapsed and display is not yet dimmed
|
||||
if (!is_dimmed && elapsed >= DIM_TIMEOUT_MS) {
|
||||
if (display->get_type() == DISPLAY_TYPE_ST7796) {
|
||||
// TFT: Put to sleep (saves power, touch stays active)
|
||||
saved_brightness = display->get_brightness();
|
||||
LowLevelDisplayST7796* tft = static_cast<LowLevelDisplayST7796*>(display);
|
||||
tft->sleep();
|
||||
printf("TFT display put to sleep after %d seconds of inactivity\n",
|
||||
DIM_TIMEOUT_MS / 1000);
|
||||
printf("Touch controller remains active - touch to wake\n");
|
||||
} else if (display->get_type() == DISPLAY_TYPE_EPAPER) {
|
||||
// E-ink: Put to sleep (turns off display)
|
||||
LowLevelDisplayEPaper* epaper = static_cast<LowLevelDisplayEPaper*>(display);
|
||||
epaper->sleep();
|
||||
printf("E-paper display put to sleep after %d seconds of inactivity\n",
|
||||
DIM_TIMEOUT_MS / 1000);
|
||||
}
|
||||
is_dimmed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// INTERRUPT HANDLERS (Keep these minimal!)
|
||||
// ============================================================================
|
||||
@@ -448,6 +553,24 @@ int main()
|
||||
uint32_t last_touch_time = 0;
|
||||
bool pending_refresh = false; // Track if we have a pending refresh
|
||||
|
||||
// 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);
|
||||
|
||||
if (display->get_type() == DISPLAY_TYPE_ST7796) {
|
||||
printf("Auto-sleep enabled: TFT will sleep after %d minutes of inactivity\n",
|
||||
DIM_TIMEOUT_MS / 60000);
|
||||
printf("Touch controller remains active to wake display\n");
|
||||
} else if (display->get_type() == DISPLAY_TYPE_EPAPER) {
|
||||
printf("Auto-sleep enabled: E-paper will sleep after %d minutes of inactivity\n",
|
||||
DIM_TIMEOUT_MS / 60000);
|
||||
}
|
||||
printf("Dimming check timer set to %d seconds\n", DIM_CHECK_INTERVAL_MS / 1000);
|
||||
|
||||
printf("\nEntering reactive game loop (Core 0 - input & logic)\n");
|
||||
printf("Display refreshes handled by Core 1\n\n");
|
||||
|
||||
@@ -476,6 +599,9 @@ int main()
|
||||
|
||||
// 3. Process input based on current state
|
||||
if (input.valid) {
|
||||
// Record user interaction for dimming timer
|
||||
record_user_interaction(display);
|
||||
|
||||
// if debugging enabled, print input event
|
||||
if (config.debug_verbose) {
|
||||
printf("Input Event: type=%d, x=%d, y=%d, gesture=0x%02X, button=%d, pressure=%d\n",
|
||||
@@ -575,6 +701,13 @@ int main()
|
||||
|
||||
// Core 0 continues immediately, Core 1 handles the refresh
|
||||
}
|
||||
|
||||
// 5. Check if display should be dimmed due to inactivity
|
||||
// This flag is set by timer alarm every DIM_CHECK_INTERVAL_MS
|
||||
if (dim_check_flag) {
|
||||
dim_check_flag = false;
|
||||
check_and_apply_dimming(display);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user