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 1 year 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