Fix some issues with the splash screen

- fix a use-after-free involving the alerts container that was
   happening when showing the first screen
 - fix some issues where the splash screen wouldn't come up as early as
   it needs to when another bootup task was making heavy use of the spi
   bus
custom
jacqueline 10 months ago
parent 9204b585ae
commit 984b874d7e
  1. 8
      src/drivers/display.cpp
  2. 1
      src/tangara/system_fsm/running.cpp
  3. 4
      src/tangara/ui/lvgl_task.cpp
  4. 2
      src/tangara/ui/screen_splash.hpp
  5. 18
      src/tangara/ui/ui_fsm.cpp
  6. 4
      src/tangara/ui/ui_fsm.hpp

@ -213,6 +213,12 @@ auto Display::SetDutyCycle(uint_fast8_t new_duty, bool fade) -> void {
}
void Display::SendInitialisationSequence(const uint8_t* data) {
// Hold the SPI bus for the entire init sequence, as otherwise SD init may
// grab it and delay showing the boot splash. The total time until boot is
// finished may be increased by doing this, but a short boot with no feedback
// feels worse than a longer boot that doesn't tell you anything.
spi_device_acquire_bus(handle_, portMAX_DELAY);
// First byte of the data is the number of commands.
for (int i = *(data++); i > 0; i--) {
uint8_t command = *(data++);
@ -232,6 +238,8 @@ void Display::SendInitialisationSequence(const uint8_t* data) {
vTaskDelay(pdMS_TO_TICKS(sleep_duration_ms));
}
}
spi_device_release_bus(handle_);
}
void Display::SendCommandWithData(uint8_t command,

@ -75,7 +75,6 @@ void Running::react(const SdDetectChanged& ev) {
}
if (ev.has_sd_card && !sStorage) {
vTaskDelay(pdMS_TO_TICKS(500));
mountStorage();
}

@ -43,8 +43,8 @@ auto UiTask::Main() -> void {
lv_group_t* current_group = nullptr;
auto* events = events::queues::Ui();
while (true) {
while (events->Service(0)) {
}
while (events->Service(0))
;
std::shared_ptr<Screen> screen = UiState::current_screen();
if (screen != current_screen_ && screen != nullptr) {

@ -20,7 +20,7 @@ class Splash : public Screen {
Splash();
~Splash();
auto canPop() -> bool override { return false; }
auto canPop() -> bool override { return true; }
private:
lv_obj_t* container_;

@ -294,7 +294,7 @@ void UiState::react(const internal::InitDisplay& ev) {
drivers::displays::InitialisationData init_data = drivers::displays::kST7735R;
// HACK: correct the display size for our prototypes.
// nvs.DisplaySize({161, 130});
// ev.nvs.DisplaySize({161, 130});
auto actual_size = ev.nvs.DisplaySize();
init_data.width = actual_size.first.value_or(init_data.width);
@ -307,12 +307,14 @@ void UiState::react(const internal::InitDisplay& ev) {
sDisplay->SetDisplayOn(!ev.gpios.IsLocked());
}
void UiState::PushScreen(std::shared_ptr<Screen> screen) {
void UiState::PushScreen(std::shared_ptr<Screen> screen, bool replace) {
lv_obj_set_parent(sAlertContainer, screen->alert());
if (sCurrentScreen) {
sCurrentScreen->onHidden();
sScreens.push(sCurrentScreen);
if (!replace) {
sScreens.push(sCurrentScreen);
}
}
sCurrentScreen = screen;
sCurrentScreen->onShown();
@ -568,7 +570,7 @@ void Lua::entry() {
registry.AddPropertyModule(
"backstack",
{
{"push", [&](lua_State* s) { return PushLuaScreen(s); }},
{"push", [&](lua_State* s) { return PushLuaScreen(s, false); }},
{"pop", [&](lua_State* s) { return PopLuaScreen(s); }},
{"reset", [&](lua_State* s) { return ResetLuaScreen(s); }},
});
@ -603,7 +605,6 @@ void Lua::entry() {
sBluetoothConnected.setDirect(bt.IsConnected());
sBluetoothDevices.setDirect(bt.KnownDevices());
sCurrentScreen.reset();
if (sServices->sd() == drivers::SdState::kMounted) {
sLua->RunScript("/sdcard/config.lua");
}
@ -611,7 +612,7 @@ void Lua::entry() {
}
}
auto Lua::PushLuaScreen(lua_State* s) -> int {
auto Lua::PushLuaScreen(lua_State* s, bool replace) -> int {
// Ensure the arg looks right before continuing.
luaL_checktype(s, 1, LUA_TTABLE);
@ -641,7 +642,7 @@ auto Lua::PushLuaScreen(lua_State* s) -> int {
// Finally, push the now-initialised screen as if it were a regular C++
// screen.
PushScreen(new_screen);
PushScreen(new_screen, replace);
return 0;
}
@ -662,12 +663,11 @@ auto Lua::ResetLuaScreen(lua_State* s) -> int {
ESP_LOGW(kTag, "ignoring reset as popping is blocked");
return 0;
}
sCurrentScreen->onHidden();
}
while (!sScreens.empty()) {
sScreens.pop();
}
return PushLuaScreen(s);
return PushLuaScreen(s, true);
}
auto Lua::QueueNext(lua_State*) -> int {

@ -83,7 +83,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
void react(const internal::ReindexDatabase&){};
protected:
void PushScreen(std::shared_ptr<Screen>);
void PushScreen(std::shared_ptr<Screen>, bool);
int PopScreen();
static std::unique_ptr<UiTask> sTask;
@ -159,7 +159,7 @@ class Lua : public UiState {
using UiState::react;
private:
auto PushLuaScreen(lua_State*) -> int;
auto PushLuaScreen(lua_State*, bool) -> int;
auto PopLuaScreen(lua_State*) -> int;
auto ResetLuaScreen(lua_State*) -> int;

Loading…
Cancel
Save