Recover Indicator display after warm reset

This commit is contained in:
mikecarper committed 2026-08-31 19:06:07 -07:00
1 parent 1abc36f636
commit 8351effff1
3 files changed
+46 -3

No files matched your search

+6 -1
View File
@@ -825,6 +825,7 @@ void halt() {
static CompanionWiFiDisplayState companion_wifi_display_state =
CompanionWiFiDisplayState::NotRendered;
static uint32_t companion_wifi_display_frames = 0;
static bool companion_display_available = false;
#if defined(COMPANION_EXCLUSIVE_WIFI_BLE)
static CompanionTransportMode companion_transport_boot_mode =
@@ -1173,9 +1174,10 @@ void halt() {
const bool idf_associated =
esp_wifi_sta_get_ap_info(&access_point) == ESP_OK;
snprintf(reply, reply_size,
"> state=%s, frames=%lu, requested=%u, services=%u, "
"> state=%s, frames=%lu, display=%u, requested=%u, services=%u, "
"wl=%d, idf=%u, IP=%s",
names[state], (unsigned long)companion_wifi_display_frames,
companion_display_available ? 1U : 0U,
companion_wifi_requested ? 1U : 0U,
companion_wifi_active ? 1U : 0U, (int)WiFi.status(),
idf_associated ? 1U : 0U,
@@ -1733,6 +1735,9 @@ void setup() {
disp->drawTextCentered(disp->width() / 2, 28, "Loading...");
disp->endFrame();
}
#if defined(ESP32) && defined(WIFI_SSID)
companion_display_available = disp != NULL;
#endif
#endif
int radioinit_attempts = 0;
+11
View File
@@ -9,6 +9,9 @@ import unittest
ROOT = Path(__file__).resolve().parents[1]
PROFILE = ROOT / "variants" / "sensecap_indicator-espnow" / "platformio.ini"
DISPLAY = ROOT / "src" / "helpers" / "ui" / "LGFXDisplay.cpp"
INDICATOR_DISPLAY = (
ROOT / "variants" / "sensecap_indicator-espnow" / "SCIndicatorDisplay.h"
)
FONT = ROOT / "variants" / "sensecap_indicator-espnow" / "sd" / "ui-font.vlw"
@@ -36,6 +39,14 @@ def numeric_flag(name: str) -> float:
class IndicatorDisplayProfileTest(unittest.TestCase):
def test_panel_cs_release_cannot_discard_initialized_display(self):
display = INDICATOR_DISPLAY.read_text()
self.assertIn("releasePanelChipSelectWithRetry()", display)
self.assertIn("if (!initialized) return false;", display)
self.assertNotIn("if (!initialized || !released) return false;", display)
self.assertIn("panel_chip_select_released =", display)
self.assertIn("void startFrame(ColorVal bkg", display)
def test_preserves_original_indicator_memory_profile(self):
profile = base_profile()
self.assertIn("board_build.arduino.memory_type = qio_opi", profile)
@@ -129,6 +129,7 @@ class SCIndicatorDisplay : public LGFXDisplay {
LGFX disp;
uint8_t expander_address = 0;
uint16_t expander_output = 0;
bool panel_chip_select_released = false;
static constexpr gpio_num_t BACKLIGHT_PIN = GPIO_NUM_45;
static constexpr uint8_t I2C_PORT = 0;
@@ -230,6 +231,20 @@ class SCIndicatorDisplay : public LGFXDisplay {
expander_output);
}
bool releasePanelChipSelectWithRetry() {
// LovyanGFX initializes the touch controller on this same I2C bus. On a
// warm ESP32-S3 reset its final transaction can briefly leave the
// expander unavailable even though the RGB panel and render buffer were
// initialized successfully. Re-open the bus and retry before LoRa starts
// using the panel's shared SCLK/MOSI pins.
for (uint8_t attempt = 0; attempt < 10; ++attempt) {
if (releasePanelChipSelect()) return true;
delay(5);
lgfx::i2c::init(I2C_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL);
}
return false;
}
public:
#if defined(INDICATOR_TRANSPORT_RENDER_PROFILE)
// Full builds always use the established 160x160 logical layout. State it
@@ -245,8 +260,13 @@ public:
bool begin() {
if (!prepareControllers()) return false;
const bool initialized = LGFXDisplay::begin();
const bool released = releasePanelChipSelect();
if (!initialized || !released) return false;
if (!initialized) return false;
// A failed CS release must not discard an otherwise valid 115 KiB render
// buffer and leave the LCD showing its pre-reset scanout forever. Keep the
// UI alive and retry from startFrame(); the common case succeeds here
// before the external LoRa radio is initialized.
panel_chip_select_released = releasePanelChipSelectWithRetry();
setBacklight(true);
size_t fontSize;
uint8_t* fontData = IndicatorFontClient::load(fontSize);
@@ -263,6 +283,13 @@ public:
return true;
}
void startFrame(ColorVal bkg = UIColor::window_bkg) override {
if (!panel_chip_select_released) {
panel_chip_select_released = releasePanelChipSelectWithRetry();
}
LGFXDisplay::startFrame(bkg);
}
#ifdef INDICATOR_WIFI_FONT_RECOVERY
void serviceFontRecovery() {
size_t fontSize = 0;