Add some placeholder splash and menu screens

Includes a bunch of misc display fixes. Most significantly, our lvgl
tickers was busted.
custom
jacqueline 2 years ago
parent 3b371cfc54
commit 65833649f4
  1. 2
      src/events/CMakeLists.txt
  2. 17
      src/events/event_queue.cpp
  3. 23
      src/events/include/event_queue.hpp
  4. 2
      src/main/main.cpp
  5. 2
      src/system_fsm/booting.cpp
  6. 5
      src/system_fsm/include/system_fsm.hpp
  7. 4
      src/ui/CMakeLists.txt
  8. 18
      src/ui/include/ui_fsm.hpp
  9. 35
      src/ui/lvgl_task.cpp
  10. 13
      src/ui/ui_fsm.cpp

@ -5,5 +5,5 @@
idf_component_register(
SRCS "event_queue.cpp"
INCLUDE_DIRS "include"
REQUIRES "tinyfsm")
REQUIRES "tinyfsm" "ui")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})

@ -14,11 +14,22 @@ namespace events {
static const std::size_t kMaxPendingEvents = 16;
EventQueue::EventQueue()
: handle_(xQueueCreate(kMaxPendingEvents, sizeof(WorkItem*))) {}
: system_handle_(xQueueCreate(kMaxPendingEvents, sizeof(WorkItem*))),
ui_handle_(xQueueCreate(kMaxPendingEvents, sizeof(WorkItem*))) {}
auto EventQueue::Service(TickType_t max_wait_time) -> bool {
auto EventQueue::ServiceSystem(TickType_t max_wait_time) -> bool {
WorkItem* item;
if (xQueueReceive(handle_, &item, max_wait_time)) {
if (xQueueReceive(system_handle_, &item, max_wait_time)) {
(*item)();
delete item;
return true;
}
return false;
}
auto EventQueue::ServiceUi(TickType_t max_wait_time) -> bool {
WorkItem* item;
if (xQueueReceive(ui_handle_, &item, max_wait_time)) {
(*item)();
delete item;
return true;

@ -7,12 +7,15 @@
#pragma once
#include <functional>
#include <type_traits>
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/queue.h"
#include "tinyfsm.hpp"
#include "ui_fsm.hpp"
namespace events {
typedef std::function<void(void)> WorkItem;
@ -24,14 +27,23 @@ class EventQueue {
return instance;
}
template <typename Event, typename... Machines>
template <typename Event, typename Machine, typename... Machines>
auto Dispatch(const Event& ev) -> void {
WorkItem* item = new WorkItem(
[=]() { tinyfsm::FsmList<Machines...>::template dispatch<Event>(ev); });
xQueueSend(handle_, &item, portMAX_DELAY);
[=]() { tinyfsm::FsmList<Machine>::template dispatch<Event>(ev); });
if (std::is_same<Machine, ui::UiState>()) {
xQueueSend(system_handle_, &item, portMAX_DELAY);
} else {
xQueueSend(ui_handle_, &item, portMAX_DELAY);
}
Dispatch<Event, Machines...>(ev);
}
auto Service(TickType_t max_wait_time) -> bool;
template <typename Event>
auto Dispatch(const Event& ev) -> void {}
auto ServiceSystem(TickType_t max_wait_time) -> bool;
auto ServiceUi(TickType_t max_wait_time) -> bool;
EventQueue(EventQueue const&) = delete;
void operator=(EventQueue const&) = delete;
@ -39,7 +51,8 @@ class EventQueue {
private:
EventQueue();
QueueHandle_t handle_;
QueueHandle_t system_handle_;
QueueHandle_t ui_handle_;
};
template <typename Event, typename... Machines>

@ -19,6 +19,6 @@ extern "C" void app_main(void) {
auto& queue = events::EventQueue::GetInstance();
while (1) {
queue.Service(portMAX_DELAY);
queue.ServiceSystem(portMAX_DELAY);
}
}

@ -26,7 +26,7 @@ namespace states {
static const char kTag[] = "BOOT";
console::AppConsole *Booting::sAppConsole;
console::AppConsole* Booting::sAppConsole;
auto Booting::entry() -> void {
ESP_LOGI(kTag, "beginning tangara boot");

@ -65,8 +65,9 @@ namespace states {
* looks good.
*/
class Booting : public SystemState {
private:
static console::AppConsole *sAppConsole;
private:
static console::AppConsole* sAppConsole;
public:
void entry() override;
void exit() override;

@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-only
idf_component_register(
SRCS "lvgl_task.cpp" "ui_fsm.cpp"
SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "screen_menu.cpp"
INCLUDE_DIRS "include"
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database")
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})

@ -8,13 +8,14 @@
#include <memory>
#include "tinyfsm.hpp"
#include "database.hpp"
#include "display.hpp"
#include "screen.hpp"
#include "storage.hpp"
#include "tinyfsm.hpp"
#include "touchwheel.hpp"
#include "system_events.hpp"
#include "touchwheel.hpp"
namespace ui {
@ -27,6 +28,10 @@ class UiState : public tinyfsm::Fsm<UiState> {
virtual ~UiState() {}
static auto current_screen() -> std::shared_ptr<Screen> {
return sCurrentScreen;
}
virtual void entry() {}
virtual void exit() {}
@ -41,6 +46,8 @@ class UiState : public tinyfsm::Fsm<UiState> {
static std::weak_ptr<drivers::TouchWheel> sTouchWheel;
static std::weak_ptr<drivers::Display> sDisplay;
static std::weak_ptr<database::Database> sDatabase;
static std::shared_ptr<Screen> sCurrentScreen;
};
namespace states {
@ -53,11 +60,14 @@ class PreBoot : public UiState {
class Splash : public UiState {
public:
void entry() override;
void react(const system_fsm::BootComplete&) override;
using UiState::react;
};
class Interactive : public UiState {};
class Interactive : public UiState {
void entry() override;
};
class FatalError : public UiState {};

@ -19,18 +19,21 @@
#include "core/lv_obj_pos.h"
#include "core/lv_obj_tree.h"
#include "esp_log.h"
#include "event_queue.hpp"
#include "font/lv_font.h"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
#include "freertos/timers.h"
#include "hal/gpio_types.h"
#include "hal/spi_types.h"
#include "lv_api_map.h"
#include "lvgl/lvgl.h"
#include "misc/lv_color.h"
#include "misc/lv_style.h"
#include "misc/lv_timer.h"
#include "tasks.hpp"
#include "touchwheel.hpp"
#include "ui_fsm.hpp"
#include "widgets/lv_label.h"
#include "display.hpp"
@ -40,33 +43,25 @@ namespace ui {
static const char* kTag = "lv_task";
auto tick_hook(TimerHandle_t xTimer) -> void {
lv_tick_inc(1);
}
void LvglMain(std::weak_ptr<drivers::TouchWheel> weak_touch_wheel,
std::weak_ptr<drivers::Display> weak_display) {
ESP_LOGI(kTag, "init lvgl");
lv_init();
// LVGL has been initialised, so we can now start reporting ticks to it.
xTimerCreate("lv_tick", pdMS_TO_TICKS(1), pdTRUE, NULL, &tick_hook);
lv_style_t style;
lv_style_init(&style);
lv_style_set_text_color(&style, LV_COLOR_MAKE(0xFF, 0, 0));
// TODO: find a nice bitmap font for this display size and density.
// lv_style_set_text_font(&style, &lv_font_montserrat_24);
auto label = lv_label_create(NULL);
lv_label_set_text(label, "COLOURS!!");
lv_obj_add_style(label, &style, 0);
std::shared_ptr<Screen> current_screen;
auto& events = events::EventQueue::GetInstance();
while (1) {
while (events.ServiceUi(0)) {
}
lv_obj_center(label);
lv_scr_load(label);
std::shared_ptr<Screen> screen = UiState::current_screen();
if (screen != current_screen && screen != nullptr) {
current_screen = screen;
// TODO(jacqueline): animate this sometimes
lv_scr_load(screen->root());
}
while (1) {
lv_timer_handler();
lv_task_handler();
// 30 FPS
// TODO(jacqueline): make this dynamic
vTaskDelay(pdMS_TO_TICKS(33));

@ -7,6 +7,9 @@
#include "ui_fsm.hpp"
#include "display.hpp"
#include "lvgl_task.hpp"
#include "screen.hpp"
#include "screen_menu.hpp"
#include "screen_splash.hpp"
#include "system_events.hpp"
#include "touchwheel.hpp"
@ -17,6 +20,8 @@ std::weak_ptr<drivers::TouchWheel> UiState::sTouchWheel;
std::weak_ptr<drivers::Display> UiState::sDisplay;
std::weak_ptr<database::Database> UiState::sDatabase;
std::shared_ptr<Screen> UiState::sCurrentScreen;
auto UiState::Init(drivers::GpioExpander* gpio_expander,
std::weak_ptr<drivers::TouchWheel> touchwheel,
std::weak_ptr<drivers::Display> display,
@ -33,10 +38,18 @@ void PreBoot::react(const system_fsm::DisplayReady& ev) {
transit<Splash>([&]() { StartLvgl(sTouchWheel, sDisplay); });
}
void Splash::entry() {
sCurrentScreen.reset(new screens::Splash());
}
void Splash::react(const system_fsm::BootComplete& ev) {
transit<Interactive>();
}
void Interactive::entry() {
// sCurrentScreen.reset(new screens::Menu());
}
} // namespace states
} // namespace ui

Loading…
Cancel
Save