summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/CMakeLists.txt3
-rw-r--r--src/drivers/include/relative_wheel.hpp52
-rw-r--r--src/drivers/relative_wheel.cpp92
-rw-r--r--src/input/CMakeLists.txt11
-rw-r--r--src/input/feedback_haptics.cpp37
-rw-r--r--src/input/include/feedback_device.hpp32
-rw-r--r--src/input/include/feedback_haptics.hpp26
-rw-r--r--src/input/include/input_device.hpp33
-rw-r--r--src/input/include/input_touch_dpad.hpp30
-rw-r--r--src/input/include/input_touch_wheel.hpp37
-rw-r--r--src/input/include/input_volume_buttons.hpp30
-rw-r--r--src/input/include/lvgl_input_driver.hpp53
-rw-r--r--src/input/input_touch_dpad.cpp35
-rw-r--r--src/input/input_touch_wheel.cpp81
-rw-r--r--src/input/input_volume_buttons.cpp26
-rw-r--r--src/input/lvgl_input_driver.cpp84
-rw-r--r--src/system_fsm/include/system_fsm.hpp1
-rw-r--r--src/system_fsm/system_fsm.cpp1
-rw-r--r--src/ui/CMakeLists.txt8
-rw-r--r--src/ui/encoder_input.cpp358
-rw-r--r--src/ui/include/encoder_input.hpp107
-rw-r--r--src/ui/include/lvgl_task.hpp7
-rw-r--r--src/ui/include/ui_fsm.hpp5
-rw-r--r--src/ui/lvgl_task.cpp15
-rw-r--r--src/ui/ui_fsm.cpp122
25 files changed, 584 insertions, 702 deletions
diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt
index 0b7ead94..891115d4 100644
--- a/src/drivers/CMakeLists.txt
+++ b/src/drivers/CMakeLists.txt
@@ -5,8 +5,7 @@
idf_component_register(
SRCS "touchwheel.cpp" "i2s_dac.cpp" "gpios.cpp" "adc.cpp" "storage.cpp"
"i2c.cpp" "bluetooth.cpp" "spi.cpp" "display.cpp" "display_init.cpp"
- "samd.cpp" "relative_wheel.cpp" "wm8523.cpp" "nvs.cpp" "haptics.cpp"
- "spiffs.cpp"
+ "samd.cpp" "wm8523.cpp" "nvs.cpp" "haptics.cpp" "spiffs.cpp"
INCLUDE_DIRS "include"
REQUIRES "esp_adc" "fatfs" "result" "lvgl" "span" "tasks" "nvs_flash" "spiffs"
"bt" "tinyfsm" "util")
diff --git a/src/drivers/include/relative_wheel.hpp b/src/drivers/include/relative_wheel.hpp
deleted file mode 100644
index e1106143..00000000
--- a/src/drivers/include/relative_wheel.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <cstdint>
-#include <functional>
-
-#include "esp_err.h"
-#include "result.hpp"
-
-#include "gpios.hpp"
-#include "touchwheel.hpp"
-
-namespace drivers {
-
-class RelativeWheel {
- public:
- explicit RelativeWheel(TouchWheel& touch);
-
- auto Update() -> void;
- auto SetEnabled(bool) -> void;
-
- auto SetSensitivity(uint8_t) -> void;
- auto GetSensitivity() -> uint8_t;
-
- auto is_clicking() const -> bool;
- auto ticks() const -> std::int_fast16_t;
-
- // Not copyable or movable.
- RelativeWheel(const RelativeWheel&) = delete;
- RelativeWheel& operator=(const RelativeWheel&) = delete;
-
- private:
- TouchWheel& touch_;
-
- bool is_enabled_;
- uint8_t sensitivity_;
- uint8_t threshold_;
-
- bool is_clicking_;
- bool was_clicking_;
- bool is_first_read_;
- std::int_fast16_t ticks_;
- uint8_t last_angle_;
-};
-
-} // namespace drivers
diff --git a/src/drivers/relative_wheel.cpp b/src/drivers/relative_wheel.cpp
deleted file mode 100644
index e90143ae..00000000
--- a/src/drivers/relative_wheel.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#include "relative_wheel.hpp"
-
-#include <stdint.h>
-#include <cstdint>
-
-#include "esp_log.h"
-
-namespace drivers {
-
-RelativeWheel::RelativeWheel(TouchWheel& touch)
- : touch_(touch),
- is_enabled_(true),
- sensitivity_(128),
- threshold_(10),
- is_clicking_(false),
- was_clicking_(false),
- is_first_read_(true),
- ticks_(0),
- last_angle_(0) {}
-
-auto RelativeWheel::Update() -> void {
- TouchWheelData d = touch_.GetTouchWheelData();
-
- is_clicking_ = d.is_button_touched;
-
- if (is_clicking_) {
- ticks_ = 0;
- return;
- }
-
- if (!d.is_wheel_touched) {
- ticks_ = 0;
- is_first_read_ = true;
- return;
- }
-
- uint8_t new_angle = d.wheel_position;
- if (is_first_read_) {
- is_first_read_ = false;
- last_angle_ = new_angle;
- return;
- }
-
- int delta = 128 - last_angle_;
- uint8_t rotated_angle = new_angle + delta;
- if (rotated_angle < 128 - threshold_) {
- ticks_ = 1;
- last_angle_ = new_angle;
- } else if (rotated_angle > 128 + threshold_) {
- ticks_ = -1;
- last_angle_ = new_angle;
- } else {
- ticks_ = 0;
- }
-}
-
-auto RelativeWheel::SetEnabled(bool en) -> void {
- is_enabled_ = en;
-}
-
-auto RelativeWheel::SetSensitivity(uint8_t val) -> void {
- sensitivity_ = val;
- int tmax = 35;
- int tmin = 5;
- threshold_ = (((255. - sensitivity_)/255.)*(tmax - tmin) + tmin);
-}
-
-auto RelativeWheel::GetSensitivity() -> uint8_t {
- return sensitivity_;
-}
-
-auto RelativeWheel::is_clicking() const -> bool {
- if (!is_enabled_) {
- return false;
- }
- return is_clicking_;
-}
-
-auto RelativeWheel::ticks() const -> std::int_fast16_t {
- if (!is_enabled_) {
- return 0;
- }
- return ticks_;
-}
-
-} // namespace drivers
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
new file mode 100644
index 00000000..92ed3d6c
--- /dev/null
+++ b/src/input/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright 2023 jacqueline <me@jacqueline.id.au>
+#
+# SPDX-License-Identifier: GPL-3.0-only
+
+idf_component_register(
+ SRCS "input_touch_wheel.cpp" "input_touch_dpad.cpp"
+ "input_volume_buttons.cpp" "lvgl_input_driver.cpp" "feedback_haptics.cpp"
+ INCLUDE_DIRS "include"
+ REQUIRES "drivers" "lvgl" "events" "system_fsm")
+
+target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/input/feedback_haptics.cpp b/src/input/feedback_haptics.cpp
new file mode 100644
index 00000000..5e83d0d6
--- /dev/null
+++ b/src/input/feedback_haptics.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "feedback_haptics.hpp"
+
+#include <cstdint>
+
+#include "lvgl/lvgl.h"
+
+#include "core/lv_event.h"
+#include "esp_log.h"
+
+#include "haptics.hpp"
+
+namespace input {
+
+using Effect = drivers::Haptics::Effect;
+
+Haptics::Haptics(drivers::Haptics& haptics_) : haptics_(haptics_) {}
+
+auto Haptics::feedback(uint8_t event_type) -> void {
+ switch (event_type) {
+ case LV_EVENT_FOCUSED:
+ haptics_.PlayWaveformEffect(Effect::kMediumClick1_100Pct);
+ break;
+ case LV_EVENT_CLICKED:
+ haptics_.PlayWaveformEffect(Effect::kSharpClick_100Pct);
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace input
diff --git a/src/input/include/feedback_device.hpp b/src/input/include/feedback_device.hpp
new file mode 100644
index 00000000..4faeeafd
--- /dev/null
+++ b/src/input/include/feedback_device.hpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace input {
+
+/*
+ * Interface for providing non-visual feedback to the user as a result of LVGL
+ * events. 'Feedback Devices' are able to observe all events that are generated
+ * by LVGL as a result of Input Devices.
+ *
+ * Implementations of this interface are a mix of hardware features (e.g. a
+ * haptic motor buzzing when your selection changes) and firmware features
+ * (e.g. playing audio feedback that describes the selected element).
+ */
+class IFeedbackDevice {
+ public:
+ virtual ~IFeedbackDevice() {}
+
+ virtual auto feedback(uint8_t event_type) -> void = 0;
+
+ // TODO: Add configuration; likely the same shape of interface that
+ // IInputDevice uses.
+};
+
+} // namespace input
diff --git a/src/input/include/feedback_haptics.hpp b/src/input/include/feedback_haptics.hpp
new file mode 100644
index 00000000..a307a429
--- /dev/null
+++ b/src/input/include/feedback_haptics.hpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "feedback_device.hpp"
+#include "haptics.hpp"
+
+namespace input {
+
+class Haptics : public IFeedbackDevice {
+ public:
+ Haptics(drivers::Haptics& haptics_);
+
+ auto feedback(uint8_t event_type) -> void override;
+
+ private:
+ drivers::Haptics& haptics_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_device.hpp b/src/input/include/input_device.hpp
new file mode 100644
index 00000000..09cf9193
--- /dev/null
+++ b/src/input/include/input_device.hpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "hal/lv_hal_indev.h"
+
+namespace input {
+
+/*
+ * Interface for all device input methods. Each 'Input Device' is polled by
+ * LVGL at regular intervals, and can effect the device either via LVGL's input
+ * device driver API, or by emitting events for other parts of the system to
+ * react to (e.g. issuing a play/pause event, or altering the volume).
+ */
+class IInputDevice {
+ public:
+ virtual ~IInputDevice() {}
+
+ virtual auto read(lv_indev_data_t* data) -> void = 0;
+
+ // TODO: Add hooks and configuration (or are hooks just one kind of
+ // configuration?)
+};
+
+} // namespace input
diff --git a/src/input/include/input_touch_dpad.hpp b/src/input/include/input_touch_dpad.hpp
new file mode 100644
index 00000000..fdb52db9
--- /dev/null
+++ b/src/input/include/input_touch_dpad.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <cstdint>
+
+#include "hal/lv_hal_indev.h"
+
+#include "haptics.hpp"
+#include "input_device.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+class TouchDPad : public IInputDevice {
+ public:
+ TouchDPad(drivers::TouchWheel&);
+
+ auto read(lv_indev_data_t* data) -> void override;
+
+ private:
+ drivers::TouchWheel& wheel_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_touch_wheel.hpp b/src/input/include/input_touch_wheel.hpp
new file mode 100644
index 00000000..a4923f21
--- /dev/null
+++ b/src/input/include/input_touch_wheel.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "hal/lv_hal_indev.h"
+
+#include "haptics.hpp"
+#include "input_device.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+class TouchWheel : public IInputDevice {
+ public:
+ TouchWheel(drivers::TouchWheel&);
+
+ auto read(lv_indev_data_t* data) -> void override;
+
+ private:
+ auto calculate_ticks(const drivers::TouchWheelData& data) -> int8_t;
+
+ drivers::TouchWheel& wheel_;
+
+ bool is_scrolling_;
+ uint8_t sensitivity_;
+ uint8_t threshold_;
+ bool is_first_read_;
+ uint8_t last_angle_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_volume_buttons.hpp b/src/input/include/input_volume_buttons.hpp
new file mode 100644
index 00000000..4ca8c16b
--- /dev/null
+++ b/src/input/include/input_volume_buttons.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "gpios.hpp"
+#include "hal/lv_hal_indev.h"
+
+#include "haptics.hpp"
+#include "input_device.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+class VolumeButtons : public IInputDevice {
+ public:
+ VolumeButtons(drivers::IGpios&);
+
+ auto read(lv_indev_data_t* data) -> void override;
+
+ private:
+ drivers::IGpios& gpios_;
+};
+
+} // namespace input
diff --git a/src/input/include/lvgl_input_driver.hpp b/src/input/include/lvgl_input_driver.hpp
new file mode 100644
index 00000000..be452368
--- /dev/null
+++ b/src/input/include/lvgl_input_driver.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <deque>
+#include <memory>
+#include <set>
+
+#include "core/lv_group.h"
+#include "feedback_device.hpp"
+#include "gpios.hpp"
+#include "hal/lv_hal_indev.h"
+
+#include "input_device.hpp"
+#include "nvs.hpp"
+#include "service_locator.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+/*
+ * Implementation of an LVGL input device. This class composes multiple
+ * IInputDevice and IFeedbackDevice instances together into a single LVGL
+ * device.
+ */
+class LvglInputDriver {
+ public:
+ LvglInputDriver(std::shared_ptr<system_fsm::ServiceLocator>);
+
+ auto read(lv_indev_data_t* data) -> void;
+ auto feedback(uint8_t) -> void;
+
+ auto registration() -> lv_indev_t* { return registration_; }
+ auto lock(bool l) -> void { is_locked_ = l; }
+
+ private:
+ std::shared_ptr<system_fsm::ServiceLocator> services_;
+
+ lv_indev_drv_t driver_;
+ lv_indev_t* registration_;
+
+ std::vector<std::unique_ptr<IInputDevice>> inputs_;
+ std::vector<std::unique_ptr<IFeedbackDevice>> feedbacks_;
+
+ bool is_locked_;
+};
+
+} // namespace input
diff --git a/src/input/input_touch_dpad.cpp b/src/input/input_touch_dpad.cpp
new file mode 100644
index 00000000..a5774ef6
--- /dev/null
+++ b/src/input/input_touch_dpad.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_touch_dpad.hpp"
+
+#include <cstdint>
+
+#include "hal/lv_hal_indev.h"
+
+#include "haptics.hpp"
+#include "input_device.hpp"
+#include "input_touch_dpad.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+static inline auto IsAngleWithin(int16_t wheel_angle,
+ int16_t target_angle,
+ int threshold) -> bool {
+ int16_t difference = (wheel_angle - target_angle + 127 + 255) % 255 - 127;
+ return difference <= threshold && difference >= -threshold;
+}
+
+TouchDPad::TouchDPad(drivers::TouchWheel& wheel) : wheel_(wheel) {}
+
+auto TouchDPad::read(lv_indev_data_t* data) -> void {
+ wheel_.Update();
+
+ // TODO: reimplement
+}
+
+} // namespace input
diff --git a/src/input/input_touch_wheel.cpp b/src/input/input_touch_wheel.cpp
new file mode 100644
index 00000000..302a17aa
--- /dev/null
+++ b/src/input/input_touch_wheel.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_touch_wheel.hpp"
+#include <stdint.h>
+
+#include <cstdint>
+
+#include "hal/lv_hal_indev.h"
+
+#include "haptics.hpp"
+#include "input_device.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+TouchWheel::TouchWheel(drivers::TouchWheel& wheel)
+ : wheel_(wheel),
+ is_scrolling_(false),
+ sensitivity_(128),
+ threshold_(10),
+ is_first_read_(true),
+ last_angle_(0) {}
+
+auto TouchWheel::read(lv_indev_data_t* data) -> void {
+ wheel_.Update();
+ auto wheel_data = wheel_.GetTouchWheelData();
+ int8_t ticks = calculate_ticks(wheel_data);
+
+ if (!wheel_data.is_wheel_touched) {
+ // User has released the wheel.
+ is_scrolling_ = false;
+ data->enc_diff = 0;
+ } else if (ticks != 0) {
+ // User is touching the wheel, and has just passed the sensitivity
+ // threshold for a scroll tick.
+ is_scrolling_ = true;
+ data->enc_diff = ticks;
+ } else {
+ // User is touching the wheel, but hasn't moved.
+ data->enc_diff = 0;
+ }
+
+ if (!is_scrolling_ && wheel_data.is_button_touched) {
+ data->state = LV_INDEV_STATE_PRESSED;
+ } else {
+ data->state = LV_INDEV_STATE_RELEASED;
+ }
+}
+
+auto TouchWheel::calculate_ticks(const drivers::TouchWheelData& data)
+ -> int8_t {
+ if (!data.is_wheel_touched) {
+ is_first_read_ = true;
+ return 0;
+ }
+
+ uint8_t new_angle = data.wheel_position;
+ if (is_first_read_) {
+ is_first_read_ = false;
+ last_angle_ = new_angle;
+ return 0;
+ }
+
+ int delta = 128 - last_angle_;
+ uint8_t rotated_angle = new_angle + delta;
+ if (rotated_angle < 128 - threshold_) {
+ last_angle_ = new_angle;
+ return 1;
+ } else if (rotated_angle > 128 + threshold_) {
+ last_angle_ = new_angle;
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+} // namespace input
diff --git a/src/input/input_volume_buttons.cpp b/src/input/input_volume_buttons.cpp
new file mode 100644
index 00000000..bf79ed55
--- /dev/null
+++ b/src/input/input_volume_buttons.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_volume_buttons.hpp"
+#include "gpios.hpp"
+
+namespace input {
+
+VolumeButtons::VolumeButtons(drivers::IGpios& gpios) : gpios_(gpios) {}
+
+auto VolumeButtons::read(lv_indev_data_t* data) -> void {
+ bool vol_up = gpios_.Get(drivers::IGpios::Pin::kKeyUp);
+ if (!vol_up) {
+ ESP_LOGI("volume", "vol up");
+ }
+
+ bool vol_down = gpios_.Get(drivers::IGpios::Pin::kKeyDown);
+ if (!vol_down) {
+ ESP_LOGI("volume", "vol down");
+ }
+}
+
+} // namespace input
diff --git a/src/input/lvgl_input_driver.cpp b/src/input/lvgl_input_driver.cpp
new file mode 100644
index 00000000..70b6eb5d
--- /dev/null
+++ b/src/input/lvgl_input_driver.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "lvgl_input_driver.hpp"
+#include <stdint.h>
+
+#include <cstdint>
+#include <memory>
+
+#include "feedback_haptics.hpp"
+#include "input_touch_wheel.hpp"
+#include "input_volume_buttons.hpp"
+#include "lvgl.h"
+#include "service_locator.hpp"
+
+[[maybe_unused]] static constexpr char kTag[] = "input";
+
+namespace input {
+
+static void read_cb(lv_indev_drv_t* drv, lv_indev_data_t* data) {
+ LvglInputDriver* instance =
+ reinterpret_cast<LvglInputDriver*>(drv->user_data);
+ instance->read(data);
+}
+
+static void feedback_cb(lv_indev_drv_t* drv, uint8_t event) {
+ LvglInputDriver* instance =
+ reinterpret_cast<LvglInputDriver*>(drv->user_data);
+ instance->feedback(event);
+}
+
+LvglInputDriver::LvglInputDriver(
+ std::shared_ptr<system_fsm::ServiceLocator> services)
+ : services_(services),
+ driver_(),
+ registration_(nullptr),
+ inputs_(),
+ feedbacks_(),
+ is_locked_(false) {
+ lv_indev_drv_init(&driver_);
+ driver_.type = LV_INDEV_TYPE_ENCODER;
+ driver_.read_cb = read_cb;
+ driver_.feedback_cb = feedback_cb;
+ driver_.user_data = this;
+
+ registration_ = lv_indev_drv_register(&driver_);
+
+ // TODO: Make these devices configurable. I'm thinking each device gets an id
+ // and then we have:
+ // - a factory to create instance given an id
+ // - add/remove device methods on LvglInputDriver that operate on ids
+ // - the user's enabled devices (+ their configuration) stored in NVS.
+ auto touchwheel = services_->touchwheel();
+ if (touchwheel) {
+ inputs_.push_back(std::make_unique<TouchWheel>(**touchwheel));
+ }
+ inputs_.push_back(std::make_unique<VolumeButtons>(services_->gpios()));
+ feedbacks_.push_back(std::make_unique<Haptics>(services_->haptics()));
+}
+
+auto LvglInputDriver::read(lv_indev_data_t* data) -> void {
+ // TODO: we should pass lock state on to the individual devices, since they
+ // may wish to either ignore the lock state, or power down until unlock.
+ if (is_locked_) {
+ return;
+ }
+ for (auto&& device : inputs_) {
+ device->read(data);
+ }
+}
+
+auto LvglInputDriver::feedback(uint8_t event) -> void {
+ if (is_locked_) {
+ return;
+ }
+ for (auto&& device : feedbacks_) {
+ device->feedback(event);
+ }
+}
+
+} // namespace input
diff --git a/src/system_fsm/include/system_fsm.hpp b/src/system_fsm/include/system_fsm.hpp
index e0a0ac7a..f01afb3f 100644
--- a/src/system_fsm/include/system_fsm.hpp
+++ b/src/system_fsm/include/system_fsm.hpp
@@ -17,7 +17,6 @@
#include "display.hpp"
#include "gpios.hpp"
#include "nvs.hpp"
-#include "relative_wheel.hpp"
#include "samd.hpp"
#include "service_locator.hpp"
#include "storage.hpp"
diff --git a/src/system_fsm/system_fsm.cpp b/src/system_fsm/system_fsm.cpp
index f502b49a..59d41c73 100644
--- a/src/system_fsm/system_fsm.cpp
+++ b/src/system_fsm/system_fsm.cpp
@@ -9,7 +9,6 @@
#include "driver/gpio.h"
#include "event_queue.hpp"
#include "gpios.hpp"
-#include "relative_wheel.hpp"
#include "service_locator.hpp"
#include "system_events.hpp"
#include "tag_parser.hpp"
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 6d45fc9f..3814e9d5 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-only
idf_component_register(
- SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "encoder_input.cpp"
- "themes.cpp" "screen.cpp" "modal.cpp" "screen_lua.cpp"
- "splash.c" "font_fusion_12.c" "font_fusion_10.c"
+ SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "themes.cpp"
+ "screen.cpp" "modal.cpp" "screen_lua.cpp" "splash.c" "font_fusion_12.c"
+ "font_fusion_10.c"
INCLUDE_DIRS "include"
- REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer" "battery" "lua" "luavgl" "esp_app_format")
+ REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer" "battery" "lua" "luavgl" "esp_app_format" "input")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/ui/encoder_input.cpp b/src/ui/encoder_input.cpp
deleted file mode 100644
index 3b5af2c1..00000000
--- a/src/ui/encoder_input.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * 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 "lvgl.h"
-
-#include "audio_events.hpp"
-#include "core/lv_event.h"
-#include "core/lv_group.h"
-#include "esp_timer.h"
-#include "event_queue.hpp"
-#include "gpios.hpp"
-#include "hal/lv_hal_indev.h"
-#include "nvs.hpp"
-#include "relative_wheel.hpp"
-#include "touchwheel.hpp"
-#include "ui_events.hpp"
-
-[[maybe_unused]] static constexpr char kTag[] = "input";
-
-constexpr int kDPadAngleThreshold = 10;
-constexpr int kLongPressDelayMs = 500;
-constexpr int kRepeatDelayMs = 250;
-
-static inline auto IsAngleWithin(int16_t wheel_angle,
- int16_t target_angle,
- int threshold) -> bool {
- int16_t difference = (wheel_angle - target_angle + 127 + 255) % 255 - 127;
- return difference <= threshold && difference >= -threshold;
-}
-
-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)),
- scroller_(std::make_unique<Scroller>()),
- mode_(drivers::NvsStorage::InputModes::kRotatingWheel),
- is_locked_(false),
- scroll_sensitivity_(10),
- is_scrolling_wheel_(false) {
- 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 {
- if (is_locked_) {
- return;
- }
-
- lv_obj_t* active_object = nullptr;
- if (registration_ && registration_->group) {
- active_object = lv_group_get_focused(registration_->group);
- }
-
- raw_wheel_.Update();
- relative_wheel_->Update();
- // GPIO (for volume buttons) updating is handled by system_fsm.
-
- uint64_t now_ms = esp_timer_get_time() / 1000;
-
- // Deal with the potential overflow of our timer.
- for (auto& it : touch_time_ms_) {
- if (it.second > now_ms) {
- // esp_timer overflowed.
- it.second = 0;
- }
- }
-
- // Check each button.
- UpdateKeyState(Keys::kVolumeUp, now_ms,
- !gpios_.Get(drivers::IGpios::Pin::kKeyUp));
- UpdateKeyState(Keys::kVolumeDown, now_ms,
- !gpios_.Get(drivers::IGpios::Pin::kKeyDown));
-
- drivers::TouchWheelData wheel_data = raw_wheel_.GetTouchWheelData();
- UpdateKeyState(Keys::kTouchWheel, now_ms, wheel_data.is_wheel_touched);
- UpdateKeyState(Keys::kTouchWheelCenter, now_ms, wheel_data.is_button_touched);
-
- UpdateKeyState(
- Keys::kDirectionalUp, now_ms,
- wheel_data.is_wheel_touched &&
- IsAngleWithin(wheel_data.wheel_position, 0, kDPadAngleThreshold));
- UpdateKeyState(
- Keys::kDirectionalLeft, now_ms,
- wheel_data.is_wheel_touched &&
- IsAngleWithin(wheel_data.wheel_position, 63, kDPadAngleThreshold));
- UpdateKeyState(
- Keys::kDirectionalDown, now_ms,
- wheel_data.is_wheel_touched &&
- IsAngleWithin(wheel_data.wheel_position, 127, kDPadAngleThreshold));
- UpdateKeyState(
- Keys::kDirectionalRight, now_ms,
- wheel_data.is_wheel_touched &&
- IsAngleWithin(wheel_data.wheel_position, 189, kDPadAngleThreshold));
-
- // When the wheel is being scrolled, we want to ensure that other inputs
- // involving the touchwheel don't trigger. This guards again two main issues:
- // - hesitating when your thumb is on a cardinal direction, causing an
- // unintentional long-press,
- // - drifting from the outside of the wheel in a way that causes the centre
- // key to be triggered.
- if (is_scrolling_wheel_) {
- UpdateKeyState(Keys::kTouchWheelCenter, now_ms, false);
- UpdateKeyState(Keys::kDirectionalUp, now_ms, false);
- UpdateKeyState(Keys::kDirectionalLeft, now_ms, false);
- UpdateKeyState(Keys::kDirectionalDown, now_ms, false);
- UpdateKeyState(Keys::kDirectionalRight, now_ms, false);
- }
-
- // Now that we've determined the correct state for all keys, we can start
- // mapping key states into actions, depending on the current control scheme.
- if (mode_ == drivers::NvsStorage::InputModes::kButtonsOnly) {
- Trigger trigger;
- data->state = LV_INDEV_STATE_RELEASED;
-
- trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- data->enc_diff = -1;
- break;
- case Trigger::kLongPress:
- events::Ui().Dispatch(internal::BackPressed{});
- break;
- }
-
- trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- data->enc_diff = 1;
- break;
- case Trigger::kLongPress:
- data->state = LV_INDEV_STATE_PRESSED;
- break;
- }
- } else if (mode_ == drivers::NvsStorage::InputModes::kDirectionalWheel) {
- Trigger trigger;
- trigger = TriggerKey(Keys::kTouchWheelCenter, KeyStyle::kLongPress, now_ms);
- data->state = trigger == Trigger::kClick ? LV_INDEV_STATE_PRESSED
- : LV_INDEV_STATE_RELEASED;
-
- trigger = TriggerKey(Keys::kDirectionalUp, KeyStyle::kRepeat, now_ms);
- if (trigger == Trigger::kClick) {
- data->enc_diff = scroller_->AddInput(now_ms, -1);
- }
-
- trigger = TriggerKey(Keys::kDirectionalDown, KeyStyle::kRepeat, now_ms);
- if (trigger == Trigger::kClick) {
- data->enc_diff = scroller_->AddInput(now_ms, 1);
- }
-
- trigger = TriggerKey(Keys::kDirectionalLeft, KeyStyle::kRepeat, now_ms);
- if (trigger == Trigger::kClick) {
- events::Ui().Dispatch(internal::BackPressed{});
- }
-
- trigger = TriggerKey(Keys::kDirectionalRight, KeyStyle::kRepeat, now_ms);
- if (trigger == Trigger::kClick) {
- // TODO: ???
- }
-
- // Cancel scrolling if the touchpad is released.
- if (!touch_time_ms_.contains(Keys::kDirectionalUp) &&
- !touch_time_ms_.contains(Keys::kDirectionalDown)) {
- data->enc_diff = scroller_->AddInput(now_ms, 0);
- }
-
- trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- events::Audio().Dispatch(audio::StepUpVolume{});
- break;
- case Trigger::kLongPress:
- break;
- }
-
- trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- events::Audio().Dispatch(audio::StepDownVolume{});
- break;
- case Trigger::kLongPress:
- break;
- }
- } else if (mode_ == drivers::NvsStorage::InputModes::kRotatingWheel) {
- if (!raw_wheel_.GetTouchWheelData().is_wheel_touched) {
- // User has released the wheel.
- is_scrolling_wheel_ = false;
- data->enc_diff = scroller_->AddInput(now_ms, 0);
- } else if (relative_wheel_->ticks() != 0) {
- // User is touching the wheel, and has just passed the sensitivity
- // threshold for a scroll tick.
- is_scrolling_wheel_ = true;
- data->enc_diff = scroller_->AddInput(now_ms, relative_wheel_->ticks());
- } else {
- // User is touching the wheel, but hasn't moved.
- data->enc_diff = 0;
- }
-
- Trigger trigger =
- TriggerKey(Keys::kTouchWheelCenter, KeyStyle::kLongPress, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- data->state = LV_INDEV_STATE_RELEASED;
- break;
- case Trigger::kClick:
- data->state = LV_INDEV_STATE_PRESSED;
- break;
- case Trigger::kLongPress:
- if (active_object) {
- lv_event_send(active_object, LV_EVENT_LONG_PRESSED, NULL);
- }
- break;
- }
-
- trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- events::Audio().Dispatch(audio::StepUpVolume{});
- break;
- case Trigger::kLongPress:
- break;
- }
-
- trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- events::Audio().Dispatch(audio::StepDownVolume{});
- break;
- case Trigger::kLongPress:
- break;
- }
-
- trigger = TriggerKey(Keys::kDirectionalLeft, KeyStyle::kLongPress, now_ms);
- switch (trigger) {
- case Trigger::kNone:
- break;
- case Trigger::kClick:
- break;
- case Trigger::kLongPress:
- events::Ui().Dispatch(internal::BackPressed{});
- break;
- }
- }
-}
-
-auto EncoderInput::scroll_sensitivity(uint8_t val) -> void {
- scroll_sensitivity_ = val;
- relative_wheel_->SetSensitivity(scroll_sensitivity_);
-}
-
-auto EncoderInput::UpdateKeyState(Keys key, uint64_t ms, bool clicked) -> void {
- if (clicked) {
- if (!touch_time_ms_.contains(key)) {
- // Key was just clicked.
- touch_time_ms_[key] = ms;
- just_released_.erase(key);
- fired_.erase(key);
- }
- return;
- }
-
- // Key is not clicked.
- if (touch_time_ms_.contains(key)) {
- // Key was just released.
- just_released_.insert(key);
- touch_time_ms_.erase(key);
- }
-}
-
-auto EncoderInput::TriggerKey(Keys key, KeyStyle s, uint64_t ms) -> Trigger {
- if (s == KeyStyle::kRepeat) {
- bool may_repeat = fired_.contains(key) && touch_time_ms_.contains(key) &&
- ms - touch_time_ms_[key] >= kRepeatDelayMs;
-
- // Repeatable keys trigger on press.
- if (touch_time_ms_.contains(key) && (!fired_.contains(key) || may_repeat)) {
- fired_.insert(key);
- return Trigger::kClick;
- } else {
- return Trigger::kNone;
- }
- } else if (s == KeyStyle::kLongPress) {
- // Long press keys trigger on release, or after holding for a delay.
- if (just_released_.contains(key)) {
- just_released_.erase(key);
- if (!fired_.contains(key)) {
- fired_.insert(key);
- return Trigger::kClick;
- }
- }
- if (touch_time_ms_.contains(key) &&
- ms - touch_time_ms_[key] >= kLongPressDelayMs &&
- !fired_.contains(key)) {
- fired_.insert(key);
- return Trigger::kLongPress;
- }
- }
-
- return Trigger::kNone;
-}
-
-auto Scroller::AddInput(uint64_t ms, int direction) -> int {
- bool dir_changed =
- ((velocity_ < 0 && direction > 0) || (velocity_ > 0 && direction < 0));
- if (direction == 0 || dir_changed) {
- last_input_ms_ = ms;
- velocity_ = 0;
- return 0;
- }
- // Decay with time
- if (last_input_ms_ > ms) {
- last_input_ms_ = 0;
- }
- uint diff = ms - last_input_ms_;
- uint diff_steps = diff / 25;
- last_input_ms_ = ms + (last_input_ms_ % 50);
- // Use powers of two for our exponential decay so we can implement decay
- // trivially via bit shifting.
- velocity_ >>= diff_steps;
-
- velocity_ += direction * 1000;
- if (velocity_ > 0) {
- return (velocity_ + 500) / 1000;
- } else {
- return (velocity_ - 500) / 1000;
- }
-}
-} // namespace ui
diff --git a/src/ui/include/encoder_input.hpp b/src/ui/include/encoder_input.hpp
deleted file mode 100644
index 7dfac071..00000000
--- a/src/ui/include/encoder_input.hpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <deque>
-#include <memory>
-#include <set>
-
-#include "core/lv_group.h"
-#include "gpios.hpp"
-#include "hal/lv_hal_indev.h"
-
-#include "nvs.hpp"
-#include "relative_wheel.hpp"
-#include "touchwheel.hpp"
-
-namespace ui {
-
-class Scroller;
-
-/*
- * 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 mode(drivers::NvsStorage::InputModes mode) { mode_ = mode; }
- auto scroll_sensitivity(uint8_t val) -> void; // Value between 0-255, used to scale the threshold
- 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_;
- std::unique_ptr<Scroller> scroller_;
-
- drivers::NvsStorage::InputModes mode_;
- bool is_locked_;
- uint8_t scroll_sensitivity_;
-
- // Every kind of distinct input that we could map to an action.
- enum class Keys {
- kVolumeUp,
- kVolumeDown,
- kTouchWheel,
- kTouchWheelCenter,
- kDirectionalUp,
- kDirectionalRight,
- kDirectionalDown,
- kDirectionalLeft,
- };
-
- // Map from a Key, to the time that it was first touched in ms. If the key is
- // currently released, where will be no entry.
- std::unordered_map<Keys, uint64_t> touch_time_ms_;
- // Set of keys that were released during the current update.
- std::set<Keys> just_released_;
- // Set of keys that have had an event fired for them since being pressed.
- std::set<Keys> fired_;
-
- bool is_scrolling_wheel_;
-
- enum class Trigger {
- kNone,
- // Regular short-click. Triggered on release for long-pressable keys,
- // triggered on the initial press for repeatable keys.
- kClick,
- kLongPress,
- };
-
- enum class KeyStyle {
- kRepeat,
- kLongPress,
- };
-
- auto UpdateKeyState(Keys key, uint64_t ms, bool clicked) -> void;
- auto TriggerKey(Keys key, KeyStyle t, uint64_t ms) -> Trigger;
-};
-
-class Scroller {
- public:
- Scroller() : last_input_ms_(0), velocity_(0) {}
-
- auto AddInput(uint64_t, int) -> int;
-
- private:
- uint64_t last_input_ms_;
- int velocity_;
-};
-
-} // namespace ui
diff --git a/src/ui/include/lvgl_task.hpp b/src/ui/include/lvgl_task.hpp
index f212ab9d..8efcbf35 100644
--- a/src/ui/include/lvgl_task.hpp
+++ b/src/ui/include/lvgl_task.hpp
@@ -15,8 +15,7 @@
#include "freertos/timers.h"
#include "display.hpp"
-#include "encoder_input.hpp"
-#include "relative_wheel.hpp"
+#include "lvgl_input_driver.hpp"
#include "screen.hpp"
#include "themes.hpp"
#include "touchwheel.hpp"
@@ -28,14 +27,14 @@ class UiTask {
static auto Start() -> UiTask*;
~UiTask();
- auto input(std::shared_ptr<EncoderInput> input) -> void;
+ auto input(std::shared_ptr<input::LvglInputDriver> input) -> void;
private:
UiTask();
auto Main() -> void;
- std::shared_ptr<EncoderInput> input_;
+ std::shared_ptr<input::LvglInputDriver> input_;
std::shared_ptr<Screen> current_screen_;
};
diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp
index 2bab487d..c238a447 100644
--- a/src/ui/include/ui_fsm.hpp
+++ b/src/ui/include/ui_fsm.hpp
@@ -14,14 +14,13 @@
#include "battery.hpp"
#include "db_events.hpp"
#include "display.hpp"
-#include "encoder_input.hpp"
#include "gpios.hpp"
#include "lua_thread.hpp"
+#include "lvgl_input_driver.hpp"
#include "lvgl_task.hpp"
#include "modal.hpp"
#include "nvs.hpp"
#include "property.hpp"
-#include "relative_wheel.hpp"
#include "screen.hpp"
#include "service_locator.hpp"
#include "storage.hpp"
@@ -92,7 +91,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<EncoderInput> sInput;
+ static std::shared_ptr<input::LvglInputDriver> sInput;
static std::stack<std::shared_ptr<Screen>> sScreens;
static std::shared_ptr<Screen> sCurrentScreen;
diff --git a/src/ui/lvgl_task.cpp b/src/ui/lvgl_task.cpp
index f0184766..4cf25c15 100644
--- a/src/ui/lvgl_task.cpp
+++ b/src/ui/lvgl_task.cpp
@@ -33,11 +33,11 @@
#include "lua.h"
#include "lv_api_map.h"
#include "lvgl/lvgl.h"
+#include "lvgl_input_driver.hpp"
#include "misc/lv_color.h"
#include "misc/lv_style.h"
#include "misc/lv_timer.h"
#include "modal.hpp"
-#include "relative_wheel.hpp"
#include "tasks.hpp"
#include "touchwheel.hpp"
#include "ui_fsm.hpp"
@@ -50,8 +50,6 @@ namespace ui {
[[maybe_unused]] static const char* kTag = "ui_task";
-static auto group_focus_cb(lv_group_t *group) -> void;
-
UiTask::UiTask() {}
UiTask::~UiTask() {
@@ -78,7 +76,6 @@ auto UiTask::Main() -> void {
if (input_ && current_screen_->group() != current_group) {
current_group = current_screen_->group();
lv_indev_set_group(input_->registration(), current_group);
- lv_group_set_focus_cb(current_group, &group_focus_cb);
}
TickType_t delay = lv_timer_handler();
@@ -86,10 +83,9 @@ auto UiTask::Main() -> void {
}
}
-auto UiTask::input(std::shared_ptr<EncoderInput> input) -> void {
+auto UiTask::input(std::shared_ptr<input::LvglInputDriver> input) -> void {
assert(current_screen_);
input_ = input;
- lv_indev_set_group(input_->registration(), current_screen_->group());
}
auto UiTask::Start() -> UiTask* {
@@ -98,11 +94,4 @@ auto UiTask::Start() -> UiTask* {
return ret;
}
-static auto group_focus_cb(lv_group_t *group) -> void {
- // TODO(robin): we probably want to vary this, configure this, etc
- events::System().Dispatch(system_fsm::HapticTrigger{
- .effect = drivers::Haptics::Effect::kMediumClick1_100Pct,
- });
-}
-
} // namespace ui
diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp
index 28733123..a9c1d3a3 100644
--- a/src/ui/ui_fsm.cpp
+++ b/src/ui/ui_fsm.cpp
@@ -30,19 +30,18 @@
#include "lauxlib.h"
#include "lua_thread.hpp"
#include "luavgl.h"
+#include "lvgl_input_driver.hpp"
#include "memory_resource.hpp"
#include "misc/lv_gc.h"
#include "audio_events.hpp"
#include "display.hpp"
-#include "encoder_input.hpp"
#include "event_queue.hpp"
#include "gpios.hpp"
#include "lua_registry.hpp"
#include "lvgl_task.hpp"
#include "nvs.hpp"
#include "property.hpp"
-#include "relative_wheel.hpp"
#include "samd.hpp"
#include "screen.hpp"
#include "screen_lua.hpp"
@@ -63,7 +62,7 @@ namespace ui {
std::unique_ptr<UiTask> UiState::sTask;
std::shared_ptr<system_fsm::ServiceLocator> UiState::sServices;
std::unique_ptr<drivers::Display> UiState::sDisplay;
-std::shared_ptr<EncoderInput> UiState::sInput;
+std::shared_ptr<input::LvglInputDriver> UiState::sInput;
std::stack<std::shared_ptr<Screen>> UiState::sScreens;
std::shared_ptr<Screen> UiState::sCurrentScreen;
@@ -234,51 +233,58 @@ lua::Property UiState::sDisplayBrightness{
return true;
}};
-lua::Property UiState::sControlsScheme{
- 0, [](const lua::LuaValue& val) {
- if (!std::holds_alternative<int>(val)) {
- return false;
- }
- drivers::NvsStorage::InputModes mode;
- switch (std::get<int>(val)) {
- case 0:
- mode = drivers::NvsStorage::InputModes::kButtonsOnly;
- break;
- case 1:
- mode = drivers::NvsStorage::InputModes::kButtonsWithWheel;
- break;
- case 2:
- mode = drivers::NvsStorage::InputModes::kDirectionalWheel;
- break;
- case 3:
- mode = drivers::NvsStorage::InputModes::kRotatingWheel;
- break;
- default:
- return false;
- }
- sServices->nvs().PrimaryInput(mode);
- sInput->mode(mode);
- return true;
- }};
-
-lua::Property UiState::sScrollSensitivity{
- 0, [](const lua::LuaValue& val) {
- std::optional<int> sensitivity = 0;
- std::visit(
- [&](auto&& v) {
- using T = std::decay_t<decltype(v)>;
- if constexpr (std::is_same_v<T, int>) {
- sensitivity = v;
- }
- },
- val);
- if (!sensitivity) {
- return false;
- }
- sInput->scroll_sensitivity(*sensitivity);
- sServices->nvs().ScrollSensitivity(*sensitivity);
- return true;
- }};
+lua::Property UiState::sControlsScheme{0, [](const lua::LuaValue& val) {
+ /*
+ if (!std::holds_alternative<int>(val))
+ { return false;
+ }
+ drivers::NvsStorage::InputModes mode;
+ switch (std::get<int>(val)) {
+ case 0:
+ mode =
+ drivers::NvsStorage::InputModes::kButtonsOnly;
+ break;
+ case 1:
+ mode =
+ drivers::NvsStorage::InputModes::kButtonsWithWheel;
+ break;
+ case 2:
+ mode =
+ drivers::NvsStorage::InputModes::kDirectionalWheel;
+ break;
+ case 3:
+ mode =
+ drivers::NvsStorage::InputModes::kRotatingWheel;
+ break;
+ default:
+ return false;
+ }
+ sServices->nvs().PrimaryInput(mode);
+ sInput->mode(mode);
+ */
+ return true;
+ }};
+
+lua::Property UiState::sScrollSensitivity{0, [](const lua::LuaValue& val) {
+ /*
+ std::optional<int> sensitivity = 0;
+ std::visit(
+ [&](auto&& v) {
+ using T =
+ std::decay_t<decltype(v)>; if
+ constexpr (std::is_same_v<T, int>) {
+ sensitivity = v;
+ }
+ },
+ val);
+ if (!sensitivity) {
+ return false;
+ }
+ sInput->scroll_sensitivity(*sensitivity);
+ sServices->nvs().ScrollSensitivity(*sensitivity);
+ */
+ return true;
+ }};
lua::Property UiState::sLockSwitch{false};
@@ -372,7 +378,7 @@ void UiState::react(const internal::ControlSchemeChanged&) {
if (!sInput) {
return;
}
- sInput->mode(sServices->nvs().PrimaryInput());
+ // sInput->mode(sServices->nvs().PrimaryInput());
}
void UiState::react(const database::event::UpdateStarted&) {
@@ -478,22 +484,8 @@ void Splash::react(const system_fsm::BootComplete& ev) {
sDisplayBrightness.Update(brightness);
sDisplay->SetBrightness(brightness);
- auto touchwheel = sServices->touchwheel();
- if (touchwheel) {
- sInput = std::make_shared<EncoderInput>(sServices->gpios(), **touchwheel);
-
- auto mode = sServices->nvs().PrimaryInput();
- sInput->mode(mode);
- sControlsScheme.Update(static_cast<int>(mode));
-
- auto sensitivity = sServices->nvs().ScrollSensitivity();
- sInput->scroll_sensitivity(sensitivity);
- sScrollSensitivity.Update(static_cast<int>(sensitivity));
-
- sTask->input(sInput);
- } else {
- ESP_LOGE(kTag, "no input devices initialised!");
- }
+ sInput = std::make_shared<input::LvglInputDriver>(sServices);
+ sTask->input(sInput);
}
void Splash::react(const system_fsm::StorageMounted&) {