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) { 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. // First byte of the data is the number of commands.
for (int i = *(data++); i > 0; i--) { for (int i = *(data++); i > 0; i--) {
uint8_t command = *(data++); uint8_t command = *(data++);
@ -232,6 +238,8 @@ void Display::SendInitialisationSequence(const uint8_t* data) {
vTaskDelay(pdMS_TO_TICKS(sleep_duration_ms)); vTaskDelay(pdMS_TO_TICKS(sleep_duration_ms));
} }
} }
spi_device_release_bus(handle_);
} }
void Display::SendCommandWithData(uint8_t command, void Display::SendCommandWithData(uint8_t command,

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

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

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

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

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

Loading…
Cancel
Save