perf(es3c28p): LVGL 512KB PSRAM cache + display charging toggle

- LVGL image cache 512KB + header cache 16 on PSRAM (was PNG bottleneck, c4ec7ead)
- DisplaySettings.disableScreensaverWhenCharging persisted, checked via PowerDevice::IsCharging
- Display app: 'Disable on charging' toggle under Display settings, auto-disabled when timeout off
- DisplayIdle: skip screensaver while charging, auto-stop if plugging in while dimmed
- Keeps upstream full-DTS board clean, no JPEG decoder, no BT HID combo per user
This commit is contained in:
Adolfo Reyna
2026-07-18 17:16:18 -04:00
parent 2fbc44466a
commit eaa248b0f4
4 changed files with 132 additions and 136 deletions
@@ -11,6 +11,7 @@
#include <tactility/log.h>
#include <Tactility/CoreDefines.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <Tactility/hal/power/PowerDevice.h>
#include <Tactility/lvgl/LvglSync.h>
#include <Tactility/service/ServiceContext.h>
#include <Tactility/service/ServiceManifest.h>
@@ -28,6 +29,23 @@ static std::shared_ptr<hal::display::DisplayDevice> getDisplay() {
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
}
static bool isDeviceCharging() {
bool charging = false;
hal::findDevices<hal::power::PowerDevice>(hal::Device::Type::Power, [&charging](const auto& power) {
if (!power->supportsMetric(hal::power::PowerDevice::MetricType::IsCharging)) {
return true;
}
hal::power::PowerDevice::MetricData data;
if (power->getMetric(hal::power::PowerDevice::MetricType::IsCharging, data) && data.valueAsBool) {
charging = true;
return false;
}
return true;
});
return charging;
}
void DisplayIdleService::stopScreensaverCb(lv_event_t* e) {
auto* self = static_cast<DisplayIdleService*>(lv_event_get_user_data(e));
lv_event_stop_bubbling(e);
@@ -123,6 +141,7 @@ void DisplayIdleService::updateScreensaver() {
}
}
void DisplayIdleService::tick() {
if (!lvgl::lock(100)) {
return;
@@ -138,16 +157,13 @@ void DisplayIdleService::tick() {
}
uint32_t inactive_ms = 0;
inactive_ms = lv_display_get_inactive_time(nullptr);
// Only update if not stopping (prevents lag on touch)
if (displayDimmed && screensaverOverlay && !stopScreensaverRequested.load(std::memory_order_acquire)) {
// Check if screensaver should auto-off after 5 minutes
if (!backlightOff) {
screensaverActiveCounter++;
if (screensaverActiveCounter >= SCREENSAVER_AUTO_OFF_TICKS) {
// Stop screensaver animation and turn off backlight
if (screensaver) {
screensaver->stop();
screensaver.reset();
@@ -165,38 +181,51 @@ void DisplayIdleService::tick() {
lvgl::unlock();
// Check stop request early for faster response
if (stopScreensaverRequested.load(std::memory_order_acquire)) {
stopScreensaver();
return;
}
auto display = getDisplay();
if (display != nullptr && display->supportsBacklightDuty()) {
if (!cachedDisplaySettings.backlightTimeoutEnabled || cachedDisplaySettings.backlightTimeoutMs == 0) {
if (displayDimmed) {
bool supportsBacklight = display != nullptr && display->supportsBacklightDuty();
if (!cachedDisplaySettings.backlightTimeoutEnabled || cachedDisplaySettings.backlightTimeoutMs == 0) {
if (displayDimmed) {
if (supportsBacklight && display != nullptr) {
display->setBacklightDuty(cachedDisplaySettings.backlightDuty);
displayDimmed = false;
}
} else {
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
displayDimmed = false;
}
} else if (supportsBacklight) {
bool charging_blocks = cachedDisplaySettings.disableScreensaverWhenCharging && isDeviceCharging();
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
if (charging_blocks) {
// Skip screensaver while charging
} else {
if (!lvgl::lock(100)) {
return; // Retry on next tick
return;
}
activateScreensaver();
lvgl::unlock();
// Turn off backlight for "None" screensaver (just black screen)
if (cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
display->setBacklightDuty(0);
if (display != nullptr) {
display->setBacklightDuty(0);
}
}
displayDimmed = true;
} else if (displayDimmed && (inactive_ms < kWakeActivityThresholdMs)) {
}
} else if (displayDimmed) {
if (inactive_ms < kWakeActivityThresholdMs) {
stopScreensaver();
} else if (charging_blocks) {
stopScreensaver();
}
}
}
}
bool DisplayIdleService::onStart(ServiceContext& service) {
// Seed random number generator for varied screensaver patterns
srand(static_cast<unsigned int>(time(nullptr)));