summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-06-01 15:28:32 +1000
committerjacqueline <me@jacqueline.id.au>2023-06-01 15:28:54 +1000
commit6fd588e970470b15936187980829916d0dbe77bb (patch)
tree1b1e73ef52bef2e41499ee5ceadc45efd408050b /src/ui
parentdb2e29a72d9b934e7b58f1d20ac3768eae484ab5 (diff)
downloadtangara-fw-6fd588e970470b15936187980829916d0dbe77bb.tar.gz
Add touchwheel -> encoder adapter
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/include/lvgl_task.hpp3
-rw-r--r--src/ui/include/screen.hpp28
-rw-r--r--src/ui/include/screen_menu.hpp29
-rw-r--r--src/ui/include/screen_splash.hpp30
-rw-r--r--src/ui/include/ui_fsm.hpp10
-rw-r--r--src/ui/include/ui_tick.hpp11
-rw-r--r--src/ui/include/wheel_encoder.hpp30
-rw-r--r--src/ui/lvgl_task.cpp16
-rw-r--r--src/ui/screen_menu.cpp52
-rw-r--r--src/ui/screen_splash.cpp38
-rw-r--r--src/ui/ui_fsm.cpp12
-rw-r--r--src/ui/wheel_encoder.cpp39
13 files changed, 283 insertions, 17 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 9a41ae0d..bd0b76f0 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-only
idf_component_register(
- SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "screen_menu.cpp"
+ SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "screen_menu.cpp" "wheel_encoder.cpp"
INCLUDE_DIRS "include"
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/ui/include/lvgl_task.hpp b/src/ui/include/lvgl_task.hpp
index 25e7dd14..8e387683 100644
--- a/src/ui/include/lvgl_task.hpp
+++ b/src/ui/include/lvgl_task.hpp
@@ -14,11 +14,12 @@
#include "freertos/task.h"
#include "display.hpp"
+#include "relative_wheel.hpp"
#include "touchwheel.hpp"
namespace ui {
-auto StartLvgl(std::weak_ptr<drivers::TouchWheel> touch_wheel,
+auto StartLvgl(std::weak_ptr<drivers::RelativeWheel> touch_wheel,
std::weak_ptr<drivers::Display> display) -> void;
} // namespace ui
diff --git a/src/ui/include/screen.hpp b/src/ui/include/screen.hpp
new file mode 100644
index 00000000..87a0d9b8
--- /dev/null
+++ b/src/ui/include/screen.hpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "core/lv_obj.h"
+#include "core/lv_obj_tree.h"
+#include "lvgl.h"
+
+namespace ui {
+
+class Screen {
+ public:
+ Screen() : root_(lv_obj_create(NULL)) {}
+ virtual ~Screen() { lv_obj_del(root_); }
+
+ auto root() -> lv_obj_t* { return root_; }
+
+ protected:
+ lv_obj_t* const root_;
+};
+
+} // namespace ui
diff --git a/src/ui/include/screen_menu.hpp b/src/ui/include/screen_menu.hpp
new file mode 100644
index 00000000..a0b07b9e
--- /dev/null
+++ b/src/ui/include/screen_menu.hpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "lvgl.h"
+
+#include "screen.hpp"
+
+namespace ui {
+namespace screens {
+
+class Menu : public Screen {
+ public:
+ Menu();
+ ~Menu();
+
+ private:
+ lv_obj_t* container_;
+ lv_obj_t* label_;
+};
+
+} // namespace screens
+} // namespace ui
diff --git a/src/ui/include/screen_splash.hpp b/src/ui/include/screen_splash.hpp
new file mode 100644
index 00000000..1ee7dd89
--- /dev/null
+++ b/src/ui/include/screen_splash.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "lvgl.h"
+
+#include "screen.hpp"
+
+namespace ui {
+namespace screens {
+
+class Splash : public Screen {
+ public:
+ Splash();
+ ~Splash();
+
+ private:
+ lv_obj_t* container_;
+ lv_obj_t* label_;
+ lv_obj_t* spinner_;
+};
+
+} // namespace screens
+} // namespace ui
diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp
index 2afcfa86..d4d23bb0 100644
--- a/src/ui/include/ui_fsm.hpp
+++ b/src/ui/include/ui_fsm.hpp
@@ -8,9 +8,9 @@
#include <memory>
+#include "relative_wheel.hpp"
#include "tinyfsm.hpp"
-#include "database.hpp"
#include "display.hpp"
#include "screen.hpp"
#include "storage.hpp"
@@ -22,9 +22,8 @@ namespace ui {
class UiState : public tinyfsm::Fsm<UiState> {
public:
static auto Init(drivers::GpioExpander* gpio_expander,
- std::weak_ptr<drivers::TouchWheel> touchwheel,
- std::weak_ptr<drivers::Display> display,
- std::weak_ptr<database::Database> database) -> void;
+ std::weak_ptr<drivers::RelativeWheel> touchwheel,
+ std::weak_ptr<drivers::Display> display) -> void;
virtual ~UiState() {}
@@ -43,9 +42,8 @@ class UiState : public tinyfsm::Fsm<UiState> {
protected:
static drivers::GpioExpander* sGpioExpander;
- static std::weak_ptr<drivers::TouchWheel> sTouchWheel;
+ static std::weak_ptr<drivers::RelativeWheel> sTouchWheel;
static std::weak_ptr<drivers::Display> sDisplay;
- static std::weak_ptr<database::Database> sDatabase;
static std::shared_ptr<Screen> sCurrentScreen;
};
diff --git a/src/ui/include/ui_tick.hpp b/src/ui/include/ui_tick.hpp
new file mode 100644
index 00000000..37f8a8bd
--- /dev/null
+++ b/src/ui/include/ui_tick.hpp
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include "esp_timer.h"
+
+#define LV_TICK_CUSTOM_SYS_TIME_EXPR (esp_timer_get_time() / 1000)
diff --git a/src/ui/include/wheel_encoder.hpp b/src/ui/include/wheel_encoder.hpp
new file mode 100644
index 00000000..0651ce0b
--- /dev/null
+++ b/src/ui/include/wheel_encoder.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "hal/lv_hal_indev.h"
+
+#include "relative_wheel.hpp"
+
+namespace ui {
+
+class TouchWheelEncoder {
+ public:
+ explicit TouchWheelEncoder(std::weak_ptr<drivers::RelativeWheel> wheel);
+
+ auto Read(lv_indev_data_t *data) -> void;
+ auto registration() -> lv_indev_t* { return registration_; }
+
+ private:
+ lv_indev_drv_t driver_;
+ lv_indev_t *registration_;
+ std::weak_ptr<drivers::RelativeWheel> wheel_;
+};
+
+} // namespace ui
diff --git a/src/ui/lvgl_task.cpp b/src/ui/lvgl_task.cpp
index f2f7c67c..1ce7fd40 100644
--- a/src/ui/lvgl_task.cpp
+++ b/src/ui/lvgl_task.cpp
@@ -15,6 +15,8 @@
#include <memory>
#include "core/lv_disp.h"
+#include "core/lv_group.h"
+#include "core/lv_indev.h"
#include "core/lv_obj.h"
#include "core/lv_obj_pos.h"
#include "core/lv_obj_tree.h"
@@ -25,15 +27,18 @@
#include "freertos/projdefs.h"
#include "freertos/timers.h"
#include "hal/gpio_types.h"
+#include "hal/lv_hal_indev.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 "relative_wheel.hpp"
#include "tasks.hpp"
#include "touchwheel.hpp"
#include "ui_fsm.hpp"
+#include "wheel_encoder.hpp"
#include "widgets/lv_label.h"
#include "display.hpp"
@@ -43,11 +48,16 @@ namespace ui {
static const char* kTag = "lv_task";
-void LvglMain(std::weak_ptr<drivers::TouchWheel> weak_touch_wheel,
+void LvglMain(std::weak_ptr<drivers::RelativeWheel> weak_touch_wheel,
std::weak_ptr<drivers::Display> weak_display) {
ESP_LOGI(kTag, "init lvgl");
lv_init();
+ TouchWheelEncoder encoder(weak_touch_wheel);
+ lv_group_t *nav_group = lv_group_create();
+ lv_group_set_default(nav_group);
+ lv_indev_set_group(encoder.registration(), nav_group);
+
std::shared_ptr<Screen> current_screen;
auto& events = events::EventQueue::GetInstance();
while (1) {
@@ -65,10 +75,12 @@ void LvglMain(std::weak_ptr<drivers::TouchWheel> weak_touch_wheel,
// 30 FPS
// TODO(jacqueline): make this dynamic
vTaskDelay(pdMS_TO_TICKS(33));
+ lv_indev_data_t d;
+ encoder.Read(&d);
}
}
-auto StartLvgl(std::weak_ptr<drivers::TouchWheel> touch_wheel,
+auto StartLvgl(std::weak_ptr<drivers::RelativeWheel> touch_wheel,
std::weak_ptr<drivers::Display> display) -> void {
tasks::StartPersistent<tasks::Type::kUi>(
[=]() { LvglMain(touch_wheel, display); });
diff --git a/src/ui/screen_menu.cpp b/src/ui/screen_menu.cpp
new file mode 100644
index 00000000..da0a7d3c
--- /dev/null
+++ b/src/ui/screen_menu.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "screen_menu.hpp"
+
+#include "core/lv_group.h"
+#include "core/lv_obj_pos.h"
+#include "extra/widgets/menu/lv_menu.h"
+#include "extra/widgets/spinner/lv_spinner.h"
+#include "hal/lv_hal_disp.h"
+#include "misc/lv_area.h"
+#include "widgets/lv_label.h"
+
+namespace ui {
+namespace screens {
+
+Menu::Menu() {
+ lv_obj_t *menu = lv_menu_create(root_);
+ lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
+ lv_obj_center(menu);
+
+ lv_obj_t *main_page = lv_menu_page_create(menu, NULL);
+
+ lv_obj_t *container;
+ lv_obj_t *label;
+
+ container = lv_menu_cont_create(main_page);
+ label = lv_label_create(container);
+ lv_label_set_text(label, "I am an item");
+
+ container = lv_menu_cont_create(main_page);
+ label = lv_label_create(container);
+ lv_label_set_text(label, "I am also an item");
+
+ container = lv_menu_cont_create(main_page);
+ label = lv_label_create(container);
+ lv_label_set_text(label, "Item #3");
+
+ container = lv_menu_cont_create(main_page);
+ label = lv_label_create(container);
+ lv_label_set_text(label, "Yay!");
+
+ lv_menu_set_page(menu, main_page);
+}
+
+Menu::~Menu() {}
+
+} // namespace screens
+} // namespace ui
diff --git a/src/ui/screen_splash.cpp b/src/ui/screen_splash.cpp
new file mode 100644
index 00000000..2b2a7b1e
--- /dev/null
+++ b/src/ui/screen_splash.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "screen_splash.hpp"
+
+#include "core/lv_obj_pos.h"
+#include "extra/widgets/spinner/lv_spinner.h"
+#include "misc/lv_area.h"
+#include "widgets/lv_label.h"
+
+namespace ui {
+namespace screens {
+
+Splash::Splash() {
+ container_ = lv_obj_create(root_);
+ lv_obj_set_align(container_, LV_ALIGN_CENTER);
+ lv_obj_set_size(container_, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
+
+ label_ = lv_label_create(container_);
+ lv_label_set_text_static(label_, "TANGARA");
+ lv_obj_set_align(label_, LV_ALIGN_TOP_MID);
+
+ spinner_ = lv_spinner_create(container_, 1000, 60);
+ lv_obj_set_size(spinner_, 32, 32);
+ lv_obj_align_to(spinner_, label_, LV_ALIGN_OUT_BOTTOM_MID, 0, 8);
+}
+
+Splash::~Splash() {
+ lv_obj_del(spinner_);
+ lv_obj_del(label_);
+ lv_obj_del(container_);
+}
+
+} // namespace screens
+} // namespace ui
diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp
index b08722aa..f12104e6 100644
--- a/src/ui/ui_fsm.cpp
+++ b/src/ui/ui_fsm.cpp
@@ -7,6 +7,7 @@
#include "ui_fsm.hpp"
#include "display.hpp"
#include "lvgl_task.hpp"
+#include "relative_wheel.hpp"
#include "screen.hpp"
#include "screen_menu.hpp"
#include "screen_splash.hpp"
@@ -16,20 +17,17 @@
namespace ui {
drivers::GpioExpander* UiState::sGpioExpander;
-std::weak_ptr<drivers::TouchWheel> UiState::sTouchWheel;
+std::weak_ptr<drivers::RelativeWheel> 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,
- std::weak_ptr<database::Database> database) -> void {
+ std::weak_ptr<drivers::RelativeWheel> touchwheel,
+ std::weak_ptr<drivers::Display> display) -> void {
sGpioExpander = gpio_expander;
sTouchWheel = touchwheel;
sDisplay = display;
- sDatabase = database;
}
namespace states {
@@ -47,7 +45,7 @@ void Splash::react(const system_fsm::BootComplete& ev) {
}
void Interactive::entry() {
- // sCurrentScreen.reset(new screens::Menu());
+ //sCurrentScreen.reset(new screens::Menu());
}
} // namespace states
diff --git a/src/ui/wheel_encoder.cpp b/src/ui/wheel_encoder.cpp
new file mode 100644
index 00000000..0129434d
--- /dev/null
+++ b/src/ui/wheel_encoder.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "wheel_encoder.hpp"
+#include "hal/lv_hal_indev.h"
+
+namespace ui {
+
+void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
+ TouchWheelEncoder *instance = reinterpret_cast<TouchWheelEncoder*>(drv->user_data);
+ instance->Read(data);
+}
+
+ TouchWheelEncoder::TouchWheelEncoder(std::weak_ptr<drivers::RelativeWheel> wheel) : wheel_(wheel) {
+ lv_indev_drv_init(&driver_);
+ driver_.type = LV_INDEV_TYPE_ENCODER;
+ driver_.read_cb = encoder_read;
+ driver_.user_data = this;
+
+ registration_ = lv_indev_drv_register(&driver_);
+ }
+
+auto TouchWheelEncoder::Read(lv_indev_data_t *data) -> void {
+ auto lock = wheel_.lock();
+ if (lock == nullptr) {
+ data->state = LV_INDEV_STATE_RELEASED;
+ data->enc_diff = 0;
+ return;
+ }
+
+ lock->Update();
+ data->state = lock->is_pressed() ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
+ data->enc_diff = lock->ticks();
+}
+
+} // namespace ui