Generalise the lvgl input driver in preparation for more input methods
This commit is contained in:
+12
-14
@@ -4,39 +4,37 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "system_fsm.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "adc.hpp"
|
||||
#include "assert.h"
|
||||
#include "audio_fsm.hpp"
|
||||
#include "battery.hpp"
|
||||
#include "bluetooth.hpp"
|
||||
#include "bluetooth_types.hpp"
|
||||
#include "core/lv_obj.h"
|
||||
#include "display_init.hpp"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "event_queue.hpp"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "freertos/projdefs.h"
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#include "adc.hpp"
|
||||
#include "audio_fsm.hpp"
|
||||
#include "battery.hpp"
|
||||
#include "bluetooth.hpp"
|
||||
#include "bluetooth_types.hpp"
|
||||
#include "display_init.hpp"
|
||||
#include "event_queue.hpp"
|
||||
#include "gpios.hpp"
|
||||
#include "lvgl/lvgl.h"
|
||||
#include "i2c.hpp"
|
||||
#include "nvs.hpp"
|
||||
#include "relative_wheel.hpp"
|
||||
#include "samd.hpp"
|
||||
#include "service_locator.hpp"
|
||||
#include "spi.hpp"
|
||||
#include "system_events.hpp"
|
||||
#include "system_fsm.hpp"
|
||||
#include "tag_parser.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
#include "track_queue.hpp"
|
||||
#include "ui_fsm.hpp"
|
||||
|
||||
#include "i2c.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
|
||||
namespace system_fsm {
|
||||
namespace states {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
idf_component_register(
|
||||
SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "screen_menu.cpp"
|
||||
"wheel_encoder.cpp" "screen_track_browser.cpp" "screen_playing.cpp"
|
||||
"encoder_input.cpp" "screen_track_browser.cpp" "screen_playing.cpp"
|
||||
"themes.cpp" "widget_top_bar.cpp" "screen.cpp" "screen_onboarding.cpp"
|
||||
"modal_progress.cpp" "modal.cpp" "modal_confirm.cpp" "screen_settings.cpp"
|
||||
"event_binding.cpp"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "encoder_input.hpp"
|
||||
|
||||
#include <sys/_stdint.h>
|
||||
#include <memory>
|
||||
|
||||
#include "core/lv_group.h"
|
||||
#include "gpios.hpp"
|
||||
#include "hal/lv_hal_indev.h"
|
||||
#include "relative_wheel.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
static void encoder_read(lv_indev_drv_t* drv, lv_indev_data_t* data) {
|
||||
EncoderInput* instance = reinterpret_cast<EncoderInput*>(drv->user_data);
|
||||
instance->Read(data);
|
||||
}
|
||||
|
||||
EncoderInput::EncoderInput(drivers::IGpios& gpios, drivers::TouchWheel& wheel)
|
||||
: gpios_(gpios),
|
||||
raw_wheel_(wheel),
|
||||
relative_wheel_(std::make_unique<drivers::RelativeWheel>(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 EncoderInput::Read(lv_indev_data_t* data) -> void {
|
||||
raw_wheel_.Update();
|
||||
relative_wheel_->Update();
|
||||
|
||||
data->enc_diff = relative_wheel_->ticks();
|
||||
data->state = relative_wheel_->is_clicking() ? LV_INDEV_STATE_PRESSED
|
||||
: LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/lv_group.h"
|
||||
#include "gpios.hpp"
|
||||
#include "hal/lv_hal_indev.h"
|
||||
|
||||
#include "relative_wheel.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
/*
|
||||
* Main input device abstracting that handles turning lower-level input device
|
||||
* drivers into events and LVGL inputs.
|
||||
*
|
||||
* As far as LVGL is concerned, this class represents an ordinary rotary
|
||||
* encoder, supporting only left and right ticks, and clicking.
|
||||
*/
|
||||
class EncoderInput {
|
||||
public:
|
||||
EncoderInput(drivers::IGpios& gpios, drivers::TouchWheel& wheel);
|
||||
|
||||
auto Read(lv_indev_data_t* data) -> void;
|
||||
auto registration() -> lv_indev_t* { return registration_; }
|
||||
|
||||
auto lock(bool l) -> void { is_locked_ = l; }
|
||||
|
||||
private:
|
||||
lv_indev_drv_t driver_;
|
||||
lv_indev_t* registration_;
|
||||
|
||||
drivers::IGpios& gpios_;
|
||||
drivers::TouchWheel& raw_wheel_;
|
||||
std::unique_ptr<drivers::RelativeWheel> relative_wheel_;
|
||||
|
||||
bool is_locked_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
@@ -15,30 +15,27 @@
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#include "display.hpp"
|
||||
#include "encoder_input.hpp"
|
||||
#include "relative_wheel.hpp"
|
||||
#include "screen.hpp"
|
||||
#include "themes.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
#include "wheel_encoder.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class UiTask {
|
||||
public:
|
||||
static auto Start() -> UiTask*;
|
||||
|
||||
~UiTask();
|
||||
|
||||
// FIXME: Once we have more input devices, this function should accept a more
|
||||
// generic interface.
|
||||
auto SetInputDevice(std::shared_ptr<TouchWheelEncoder> dev) -> void;
|
||||
auto input(std::shared_ptr<EncoderInput> input) -> void;
|
||||
|
||||
private:
|
||||
UiTask();
|
||||
|
||||
auto Main() -> void;
|
||||
|
||||
std::shared_ptr<TouchWheelEncoder> input_device_;
|
||||
std::shared_ptr<EncoderInput> input_;
|
||||
std::shared_ptr<Screen> current_screen_;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "tinyfsm.hpp"
|
||||
|
||||
#include "display.hpp"
|
||||
#include "encoder_input.hpp"
|
||||
#include "modal.hpp"
|
||||
#include "screen.hpp"
|
||||
#include "storage.hpp"
|
||||
@@ -34,7 +35,6 @@
|
||||
#include "track.hpp"
|
||||
#include "track_queue.hpp"
|
||||
#include "ui_events.hpp"
|
||||
#include "wheel_encoder.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -87,7 +87,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
||||
static std::unique_ptr<UiTask> sTask;
|
||||
static std::shared_ptr<system_fsm::ServiceLocator> sServices;
|
||||
static std::unique_ptr<drivers::Display> sDisplay;
|
||||
static std::shared_ptr<TouchWheelEncoder> sEncoder;
|
||||
static std::shared_ptr<EncoderInput> sInput;
|
||||
|
||||
static std::stack<std::shared_ptr<Screen>> sScreens;
|
||||
static std::shared_ptr<Screen> sCurrentScreen;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/lv_group.h"
|
||||
#include "hal/lv_hal_indev.h"
|
||||
|
||||
#include "relative_wheel.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class TouchWheelEncoder {
|
||||
public:
|
||||
explicit TouchWheelEncoder(std::unique_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_;
|
||||
|
||||
lv_key_t last_key_;
|
||||
std::unique_ptr<drivers::RelativeWheel> wheel_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
+8
-10
@@ -40,7 +40,6 @@
|
||||
#include "tasks.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
#include "ui_fsm.hpp"
|
||||
#include "wheel_encoder.hpp"
|
||||
#include "widgets/lv_label.h"
|
||||
|
||||
#include "display.hpp"
|
||||
@@ -67,15 +66,15 @@ auto UiTask::Main() -> void {
|
||||
std::shared_ptr<Screen> screen = UiState::current_screen();
|
||||
if (screen != current_screen_ && screen != nullptr) {
|
||||
lv_scr_load(screen->root());
|
||||
if (input_device_) {
|
||||
lv_indev_set_group(input_device_->registration(), screen->group());
|
||||
if (input_) {
|
||||
lv_indev_set_group(input_->registration(), screen->group());
|
||||
}
|
||||
current_screen_ = screen;
|
||||
}
|
||||
|
||||
if (input_device_ && current_screen_->group() != current_group) {
|
||||
if (input_ && current_screen_->group() != current_group) {
|
||||
current_group = current_screen_->group();
|
||||
lv_indev_set_group(input_device_->registration(), current_group);
|
||||
lv_indev_set_group(input_->registration(), current_group);
|
||||
}
|
||||
|
||||
if (current_screen_) {
|
||||
@@ -87,11 +86,10 @@ auto UiTask::Main() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto UiTask::SetInputDevice(std::shared_ptr<TouchWheelEncoder> dev) -> void {
|
||||
input_device_ = std::move(dev);
|
||||
if (current_screen_ && input_device_) {
|
||||
lv_indev_set_group(input_device_->registration(), current_screen_->group());
|
||||
}
|
||||
auto UiTask::input(std::shared_ptr<EncoderInput> input) -> void {
|
||||
assert(current_screen_);
|
||||
input_ = input;
|
||||
lv_indev_set_group(input_->registration(), current_screen_->group());
|
||||
}
|
||||
|
||||
auto UiTask::Start() -> UiTask* {
|
||||
|
||||
+5
-8
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "audio_events.hpp"
|
||||
#include "display.hpp"
|
||||
#include "encoder_input.hpp"
|
||||
#include "event_queue.hpp"
|
||||
#include "gpios.hpp"
|
||||
#include "lvgl_task.hpp"
|
||||
@@ -35,7 +36,6 @@
|
||||
#include "touchwheel.hpp"
|
||||
#include "track_queue.hpp"
|
||||
#include "ui_events.hpp"
|
||||
#include "wheel_encoder.hpp"
|
||||
#include "widget_top_bar.hpp"
|
||||
|
||||
namespace ui {
|
||||
@@ -47,7 +47,7 @@ static const std::size_t kRecordsPerPage = 15;
|
||||
std::unique_ptr<UiTask> UiState::sTask;
|
||||
std::shared_ptr<system_fsm::ServiceLocator> UiState::sServices;
|
||||
std::unique_ptr<drivers::Display> UiState::sDisplay;
|
||||
std::shared_ptr<TouchWheelEncoder> UiState::sEncoder;
|
||||
std::shared_ptr<EncoderInput> UiState::sInput;
|
||||
|
||||
std::stack<std::shared_ptr<Screen>> UiState::sScreens;
|
||||
std::shared_ptr<Screen> UiState::sCurrentScreen;
|
||||
@@ -88,8 +88,7 @@ void UiState::PopScreen() {
|
||||
|
||||
void UiState::react(const system_fsm::KeyLockChanged& ev) {
|
||||
sDisplay->SetDisplayOn(ev.falling);
|
||||
sTask->SetInputDevice(ev.falling ? sEncoder
|
||||
: std::shared_ptr<TouchWheelEncoder>());
|
||||
sInput->lock(!ev.falling);
|
||||
}
|
||||
|
||||
void UiState::react(const system_fsm::BatteryStateChanged& ev) {
|
||||
@@ -138,10 +137,8 @@ void Splash::react(const system_fsm::BootComplete& ev) {
|
||||
|
||||
auto touchwheel = sServices->touchwheel();
|
||||
if (touchwheel) {
|
||||
auto relative_wheel =
|
||||
std::make_unique<drivers::RelativeWheel>(**touchwheel);
|
||||
sEncoder = std::make_shared<TouchWheelEncoder>(std::move(relative_wheel));
|
||||
sTask->SetInputDevice(sEncoder);
|
||||
sInput = std::make_shared<EncoderInput>(sServices->gpios(), **touchwheel);
|
||||
sTask->input(sInput);
|
||||
} else {
|
||||
ESP_LOGE(kTag, "no input devices initialised!");
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "wheel_encoder.hpp"
|
||||
#include <sys/_stdint.h>
|
||||
#include "core/lv_group.h"
|
||||
#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);
|
||||
}
|
||||
|
||||
void encoder_feedback(lv_indev_drv_t* drv, uint8_t event_code) {
|
||||
ESP_LOGI("Touchwheel Event", "Event code: %d", event_code);
|
||||
}
|
||||
|
||||
TouchWheelEncoder::TouchWheelEncoder(
|
||||
std::unique_ptr<drivers::RelativeWheel> wheel)
|
||||
: last_key_(0), wheel_(std::move(wheel)) {
|
||||
lv_indev_drv_init(&driver_);
|
||||
driver_.type = LV_INDEV_TYPE_ENCODER;
|
||||
driver_.read_cb = encoder_read;
|
||||
// driver_.feedback_cb = encoder_feedback;
|
||||
driver_.user_data = this;
|
||||
|
||||
registration_ = lv_indev_drv_register(&driver_);
|
||||
}
|
||||
|
||||
auto TouchWheelEncoder::Read(lv_indev_data_t* data) -> void {
|
||||
wheel_->Update();
|
||||
|
||||
data->enc_diff = wheel_->ticks();
|
||||
data->state =
|
||||
wheel_->is_clicking() ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
Reference in New Issue
Block a user