summaryrefslogtreecommitdiff
path: root/src/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/input')
-rw-r--r--src/input/CMakeLists.txt3
-rw-r--r--src/input/device_factory.cpp58
-rw-r--r--src/input/include/device_factory.hpp39
-rw-r--r--src/input/include/input_device.hpp6
-rw-r--r--src/input/include/input_nav_buttons.hpp34
-rw-r--r--src/input/include/input_touch_dpad.hpp6
-rw-r--r--src/input/include/input_touch_wheel.hpp20
-rw-r--r--src/input/include/input_trigger.hpp37
-rw-r--r--src/input/include/input_volume_buttons.hpp4
-rw-r--r--src/input/include/lvgl_input_driver.hpp17
-rw-r--r--src/input/input_nav_buttons.cpp44
-rw-r--r--src/input/input_touch_dpad.cpp42
-rw-r--r--src/input/input_touch_wheel.cpp76
-rw-r--r--src/input/input_trigger.cpp72
-rw-r--r--src/input/input_volume_buttons.cpp17
-rw-r--r--src/input/lvgl_input_driver.cpp59
16 files changed, 494 insertions, 40 deletions
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 92ed3d6c..3bc3e39d 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -3,8 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-only
idf_component_register(
- SRCS "input_touch_wheel.cpp" "input_touch_dpad.cpp"
+ SRCS "input_touch_wheel.cpp" "input_touch_dpad.cpp" "input_trigger.cpp"
"input_volume_buttons.cpp" "lvgl_input_driver.cpp" "feedback_haptics.cpp"
+ "device_factory.cpp" "input_nav_buttons.cpp"
INCLUDE_DIRS "include"
REQUIRES "drivers" "lvgl" "events" "system_fsm")
diff --git a/src/input/device_factory.cpp b/src/input/device_factory.cpp
new file mode 100644
index 00000000..65f4d785
--- /dev/null
+++ b/src/input/device_factory.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "device_factory.hpp"
+
+#include <memory>
+
+#include "feedback_haptics.hpp"
+#include "input_device.hpp"
+#include "input_nav_buttons.hpp"
+#include "input_touch_dpad.hpp"
+#include "input_touch_wheel.hpp"
+#include "input_volume_buttons.hpp"
+
+namespace input {
+
+DeviceFactory::DeviceFactory(
+ std::shared_ptr<system_fsm::ServiceLocator> services)
+ : services_(services) {
+ if (services->touchwheel()) {
+ wheel_ =
+ std::make_shared<TouchWheel>(services->nvs(), **services->touchwheel());
+ }
+}
+
+auto DeviceFactory::createInputs(drivers::NvsStorage::InputModes mode)
+ -> std::vector<std::shared_ptr<IInputDevice>> {
+ std::vector<std::shared_ptr<IInputDevice>> ret;
+ switch (mode) {
+ case drivers::NvsStorage::InputModes::kButtonsOnly:
+ ret.push_back(std::make_shared<NavButtons>(services_->gpios()));
+ break;
+ case drivers::NvsStorage::InputModes::kDirectionalWheel:
+ ret.push_back(std::make_shared<VolumeButtons>(services_->gpios()));
+ if (services_->touchwheel()) {
+ ret.push_back(std::make_shared<TouchDPad>(**services_->touchwheel()));
+ }
+ break;
+ case drivers::NvsStorage::InputModes::kRotatingWheel:
+ default: // Don't break input over a bad enum value.
+ ret.push_back(std::make_shared<VolumeButtons>(services_->gpios()));
+ if (wheel_) {
+ ret.push_back(wheel_);
+ }
+ break;
+ }
+ return ret;
+}
+
+auto DeviceFactory::createFeedbacks()
+ -> std::vector<std::shared_ptr<IFeedbackDevice>> {
+ return {std::make_shared<Haptics>(services_->haptics())};
+}
+
+} // namespace input
diff --git a/src/input/include/device_factory.hpp b/src/input/include/device_factory.hpp
new file mode 100644
index 00000000..dd9c7133
--- /dev/null
+++ b/src/input/include/device_factory.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "feedback_device.hpp"
+#include "input_device.hpp"
+#include "input_touch_wheel.hpp"
+#include "nvs.hpp"
+#include "service_locator.hpp"
+
+namespace input {
+
+class DeviceFactory {
+ public:
+ DeviceFactory(std::shared_ptr<system_fsm::ServiceLocator>);
+
+ auto createInputs(drivers::NvsStorage::InputModes mode)
+ -> std::vector<std::shared_ptr<IInputDevice>>;
+
+ auto createFeedbacks() -> std::vector<std::shared_ptr<IFeedbackDevice>>;
+
+ auto touch_wheel() -> std::shared_ptr<TouchWheel> { return wheel_; }
+
+ private:
+ std::shared_ptr<system_fsm::ServiceLocator> services_;
+
+ // HACK: the touchwheel is current a special case, since it's the only input
+ // device that has some kind of setting/configuration; scroll sensitivity.
+ std::shared_ptr<TouchWheel> wheel_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_device.hpp b/src/input/include/input_device.hpp
index 09cf9193..5fc3e066 100644
--- a/src/input/include/input_device.hpp
+++ b/src/input/include/input_device.hpp
@@ -11,6 +11,7 @@
#include <vector>
#include "hal/lv_hal_indev.h"
+#include "property.hpp"
namespace input {
@@ -28,6 +29,11 @@ class IInputDevice {
// TODO: Add hooks and configuration (or are hooks just one kind of
// configuration?)
+
+ virtual auto settings()
+ -> std::vector<std::pair<std::string, lua::Property>> {
+ return {};
+ }
};
} // namespace input
diff --git a/src/input/include/input_nav_buttons.hpp b/src/input/include/input_nav_buttons.hpp
new file mode 100644
index 00000000..29a19a16
--- /dev/null
+++ b/src/input/include/input_nav_buttons.hpp
@@ -0,0 +1,34 @@
+/*
+ * 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 "input_trigger.hpp"
+#include "touchwheel.hpp"
+
+namespace input {
+
+class NavButtons : public IInputDevice {
+ public:
+ NavButtons(drivers::IGpios&);
+
+ auto read(lv_indev_data_t* data) -> void override;
+
+ private:
+ drivers::IGpios& gpios_;
+
+ Trigger up_;
+ Trigger down_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_touch_dpad.hpp b/src/input/include/input_touch_dpad.hpp
index fdb52db9..03936acb 100644
--- a/src/input/include/input_touch_dpad.hpp
+++ b/src/input/include/input_touch_dpad.hpp
@@ -13,6 +13,7 @@
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_trigger.hpp"
#include "touchwheel.hpp"
namespace input {
@@ -25,6 +26,11 @@ class TouchDPad : public IInputDevice {
private:
drivers::TouchWheel& wheel_;
+
+ Trigger up_;
+ Trigger right_;
+ Trigger down_;
+ Trigger left_;
};
} // namespace input
diff --git a/src/input/include/input_touch_wheel.hpp b/src/input/include/input_touch_wheel.hpp
index a4923f21..c81cbb1a 100644
--- a/src/input/include/input_touch_wheel.hpp
+++ b/src/input/include/input_touch_wheel.hpp
@@ -6,29 +6,43 @@
#pragma once
+#include <sys/_stdint.h>
#include <cstdint>
#include "hal/lv_hal_indev.h"
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_trigger.hpp"
+#include "nvs.hpp"
+#include "property.hpp"
#include "touchwheel.hpp"
namespace input {
class TouchWheel : public IInputDevice {
public:
- TouchWheel(drivers::TouchWheel&);
+ TouchWheel(drivers::NvsStorage&, drivers::TouchWheel&);
auto read(lv_indev_data_t* data) -> void override;
+ auto sensitivity() -> lua::Property&;
+
private:
- auto calculate_ticks(const drivers::TouchWheelData& data) -> int8_t;
+ auto calculateTicks(const drivers::TouchWheelData& data) -> int8_t;
+ auto calculateThreshold(uint8_t sensitivity) -> uint8_t;
+ drivers::NvsStorage& nvs_;
drivers::TouchWheel& wheel_;
+ lua::Property sensitivity_;
+
+ Trigger up_;
+ Trigger right_;
+ Trigger down_;
+ Trigger left_;
+
bool is_scrolling_;
- uint8_t sensitivity_;
uint8_t threshold_;
bool is_first_read_;
uint8_t last_angle_;
diff --git a/src/input/include/input_trigger.hpp b/src/input/include/input_trigger.hpp
new file mode 100644
index 00000000..599b796b
--- /dev/null
+++ b/src/input/include/input_trigger.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <optional>
+
+#include "hal/lv_hal_indev.h"
+
+namespace input {
+
+const uint16_t kLongPressDelayMs = LV_INDEV_DEF_LONG_PRESS_TIME;
+const uint16_t kRepeatDelayMs = LV_INDEV_DEF_LONG_PRESS_REP_TIME;
+
+class Trigger {
+ public:
+ enum class State {
+ kNone,
+ kClick,
+ kLongPress,
+ kRepeatPress,
+ };
+
+ Trigger();
+
+ auto update(bool is_pressed) -> State;
+
+ private:
+ std::optional<uint64_t> touch_time_ms_;
+ uint16_t times_fired_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_volume_buttons.hpp b/src/input/include/input_volume_buttons.hpp
index 4ca8c16b..162ca8d9 100644
--- a/src/input/include/input_volume_buttons.hpp
+++ b/src/input/include/input_volume_buttons.hpp
@@ -13,6 +13,7 @@
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_trigger.hpp"
#include "touchwheel.hpp"
namespace input {
@@ -25,6 +26,9 @@ class VolumeButtons : public IInputDevice {
private:
drivers::IGpios& gpios_;
+
+ Trigger up_;
+ Trigger down_;
};
} // namespace input
diff --git a/src/input/include/lvgl_input_driver.hpp b/src/input/include/lvgl_input_driver.hpp
index be452368..257ccb28 100644
--- a/src/input/include/lvgl_input_driver.hpp
+++ b/src/input/include/lvgl_input_driver.hpp
@@ -6,19 +6,20 @@
#pragma once
-#include <stdint.h>
+#include <cstdint>
#include <deque>
#include <memory>
#include <set>
#include "core/lv_group.h"
+#include "device_factory.hpp"
#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 "property.hpp"
#include "touchwheel.hpp"
namespace input {
@@ -30,7 +31,9 @@ namespace input {
*/
class LvglInputDriver {
public:
- LvglInputDriver(std::shared_ptr<system_fsm::ServiceLocator>);
+ LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory&);
+
+ auto mode() -> lua::Property& { return mode_; }
auto read(lv_indev_data_t* data) -> void;
auto feedback(uint8_t) -> void;
@@ -39,13 +42,15 @@ class LvglInputDriver {
auto lock(bool l) -> void { is_locked_ = l; }
private:
- std::shared_ptr<system_fsm::ServiceLocator> services_;
+ drivers::NvsStorage& nvs_;
+ DeviceFactory& factory_;
+ lua::Property mode_;
lv_indev_drv_t driver_;
lv_indev_t* registration_;
- std::vector<std::unique_ptr<IInputDevice>> inputs_;
- std::vector<std::unique_ptr<IFeedbackDevice>> feedbacks_;
+ std::vector<std::shared_ptr<IInputDevice>> inputs_;
+ std::vector<std::shared_ptr<IFeedbackDevice>> feedbacks_;
bool is_locked_;
};
diff --git a/src/input/input_nav_buttons.cpp b/src/input/input_nav_buttons.cpp
new file mode 100644
index 00000000..d83568c8
--- /dev/null
+++ b/src/input/input_nav_buttons.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_nav_buttons.hpp"
+
+#include "event_queue.hpp"
+#include "gpios.hpp"
+#include "hal/lv_hal_indev.h"
+
+namespace input {
+
+NavButtons::NavButtons(drivers::IGpios& gpios) : gpios_(gpios) {}
+
+auto NavButtons::read(lv_indev_data_t* data) -> void {
+ bool vol_up = gpios_.Get(drivers::IGpios::Pin::kKeyUp);
+ switch (up_.update(!vol_up)) {
+ case Trigger::State::kClick:
+ data->enc_diff = -1;
+ break;
+ case Trigger::State::kLongPress:
+ events::Ui().Dispatch(ui::internal::BackPressed{});
+ break;
+ default:
+ break;
+ }
+
+ bool vol_down = gpios_.Get(drivers::IGpios::Pin::kKeyDown);
+ switch (down_.update(!vol_down)) {
+ case Trigger::State::kClick:
+ data->enc_diff = 1;
+ break;
+ case Trigger::State::kLongPress:
+ data->state = LV_INDEV_STATE_PRESSED;
+ break;
+ default:
+ data->state = LV_INDEV_STATE_RELEASED;
+ break;
+ }
+}
+
+} // namespace input
diff --git a/src/input/input_touch_dpad.cpp b/src/input/input_touch_dpad.cpp
index a5774ef6..828d6b59 100644
--- a/src/input/input_touch_dpad.cpp
+++ b/src/input/input_touch_dpad.cpp
@@ -10,6 +10,7 @@
#include "hal/lv_hal_indev.h"
+#include "event_queue.hpp"
#include "haptics.hpp"
#include "input_device.hpp"
#include "input_touch_dpad.hpp"
@@ -28,8 +29,47 @@ TouchDPad::TouchDPad(drivers::TouchWheel& wheel) : wheel_(wheel) {}
auto TouchDPad::read(lv_indev_data_t* data) -> void {
wheel_.Update();
+ auto wheel_data = wheel_.GetTouchWheelData();
- // TODO: reimplement
+ if (wheel_data.is_button_touched) {
+ data->state = LV_INDEV_STATE_PRESSED;
+ } else {
+ data->state = LV_INDEV_STATE_RELEASED;
+ }
+
+ switch (up_.update(
+ wheel_data.is_wheel_touched &&
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 0, 32))) {
+ case Trigger::State::kNone:
+ break;
+ default:
+ data->enc_diff = -1;
+ break;
+ }
+ switch (right_.update(
+ wheel_data.is_wheel_touched &&
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 192, 32))) {
+ default:
+ break;
+ }
+ switch (down_.update(
+ wheel_data.is_wheel_touched &&
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 128, 32))) {
+ case Trigger::State::kNone:
+ break;
+ default:
+ data->enc_diff = 1;
+ break;
+ }
+ switch (left_.update(
+ wheel_data.is_wheel_touched &&
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 64, 32))) {
+ case Trigger::State::kLongPress:
+ events::Ui().Dispatch(ui::internal::BackPressed{});
+ break;
+ default:
+ break;
+ }
}
} // namespace input
diff --git a/src/input/input_touch_wheel.cpp b/src/input/input_touch_wheel.cpp
index 302a17aa..7670e342 100644
--- a/src/input/input_touch_wheel.cpp
+++ b/src/input/input_touch_wheel.cpp
@@ -8,27 +8,46 @@
#include <stdint.h>
#include <cstdint>
+#include <variant>
+#include "event_queue.hpp"
#include "hal/lv_hal_indev.h"
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_trigger.hpp"
+#include "nvs.hpp"
+#include "property.hpp"
#include "touchwheel.hpp"
+#include "ui_events.hpp"
namespace input {
-TouchWheel::TouchWheel(drivers::TouchWheel& wheel)
- : wheel_(wheel),
+TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
+ : nvs_(nvs),
+ wheel_(wheel),
+ sensitivity_(static_cast<int>(nvs.ScrollSensitivity()),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ int int_val = std::get<int>(val);
+ if (int_val < 0 || int_val > UINT8_MAX) {
+ return false;
+ }
+ nvs.ScrollSensitivity(int_val);
+ threshold_ = calculateThreshold(int_val);
+ return true;
+ }),
is_scrolling_(false),
- sensitivity_(128),
- threshold_(10),
+ threshold_(calculateThreshold(nvs.ScrollSensitivity())),
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);
+ int8_t ticks = calculateTicks(wheel_data);
if (!wheel_data.is_wheel_touched) {
// User has released the wheel.
@@ -49,10 +68,47 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void {
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
+
+ // If the user is touching the wheel but not scrolling, then they may be
+ // clicking on one of the wheel's cardinal directions.
+ bool pressing = wheel_data.is_wheel_touched && !is_scrolling_;
+
+ switch (up_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 0, 32))) {
+ case Trigger::State::kLongPress:
+ data->enc_diff = INT16_MIN;
+ break;
+ default:
+ break;
+ }
+ switch (right_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 192, 32))) {
+ default:
+ break;
+ }
+ switch (down_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 128, 32))) {
+ case Trigger::State::kLongPress:
+ data->enc_diff = INT16_MAX;
+ break;
+ default:
+ break;
+ }
+ switch (left_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 64, 32))) {
+ case Trigger::State::kLongPress:
+ events::Ui().Dispatch(ui::internal::BackPressed{});
+ break;
+ default:
+ break;
+ }
+}
+
+auto TouchWheel::sensitivity() -> lua::Property& {
+ return sensitivity_;
}
-auto TouchWheel::calculate_ticks(const drivers::TouchWheelData& data)
- -> int8_t {
+auto TouchWheel::calculateTicks(const drivers::TouchWheelData& data) -> int8_t {
if (!data.is_wheel_touched) {
is_first_read_ = true;
return 0;
@@ -78,4 +134,10 @@ auto TouchWheel::calculate_ticks(const drivers::TouchWheelData& data)
}
}
+auto TouchWheel::calculateThreshold(uint8_t sensitivity) -> uint8_t {
+ int tmax = 35;
+ int tmin = 5;
+ return (((255. - sensitivity) / 255.) * (tmax - tmin) + tmin);
+}
+
} // namespace input
diff --git a/src/input/input_trigger.cpp b/src/input/input_trigger.cpp
new file mode 100644
index 00000000..9485ecb4
--- /dev/null
+++ b/src/input/input_trigger.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_trigger.hpp"
+#include <sys/_stdint.h>
+
+#include <cstdint>
+#include "esp_log.h"
+#include "esp_timer.h"
+
+namespace input {
+
+Trigger::Trigger() : touch_time_ms_(), times_fired_(0) {}
+
+auto Trigger::update(bool is_pressed) -> State {
+ // Bail out early if we're in a steady-state of not pressed.
+ if (!is_pressed && !touch_time_ms_) {
+ return State::kNone;
+ }
+
+ uint64_t now_ms = esp_timer_get_time() / 1000;
+
+ // Initial press of this key: record the current time, and report that we
+ // haven't triggered yet.
+ if (is_pressed && !touch_time_ms_) {
+ touch_time_ms_ = now_ms;
+ times_fired_ = 0;
+ return State::kNone;
+ }
+
+ // The key was released. If there were no long-press events fired during the
+ // press, then this was a standard click.
+ if (!is_pressed && touch_time_ms_) {
+ touch_time_ms_.reset();
+ if (times_fired_ == 0) {
+ return State::kClick;
+ } else {
+ return State::kNone;
+ }
+ }
+
+ // Now the more complicated case: the user is continuing to press the button.
+ if (times_fired_ == 0) {
+ // We haven't fired yet, so we wait for the long-press event.
+ if (now_ms - *touch_time_ms_ >= kLongPressDelayMs) {
+ times_fired_++;
+ return State::kLongPress;
+ }
+ } else {
+ // We've already fired at least once. How long has the user been holding
+ // the key for?
+ uint64_t time_since_long_press =
+ now_ms - (*touch_time_ms_ + kLongPressDelayMs);
+
+ // How many times should we have fired?
+ // 1 initial fire (for the long-press), plus one additional fire every
+ // kRepeatDelayMs since the long-press event.
+ uint16_t expected_times_fired =
+ 1 + (time_since_long_press / kRepeatDelayMs);
+ if (times_fired_ < expected_times_fired) {
+ times_fired_++;
+ return State::kRepeatPress;
+ }
+ }
+
+ return State::kNone;
+}
+
+} // namespace input
diff --git a/src/input/input_volume_buttons.cpp b/src/input/input_volume_buttons.cpp
index bf79ed55..0413222c 100644
--- a/src/input/input_volume_buttons.cpp
+++ b/src/input/input_volume_buttons.cpp
@@ -5,6 +5,7 @@
*/
#include "input_volume_buttons.hpp"
+#include "event_queue.hpp"
#include "gpios.hpp"
namespace input {
@@ -13,13 +14,21 @@ 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");
+ switch (up_.update(!vol_up)) {
+ case Trigger::State::kNone:
+ break;
+ default:
+ events::Audio().Dispatch(audio::StepUpVolume{});
+ break;
}
bool vol_down = gpios_.Get(drivers::IGpios::Pin::kKeyDown);
- if (!vol_down) {
- ESP_LOGI("volume", "vol down");
+ switch (down_.update(!vol_down)) {
+ case Trigger::State::kNone:
+ break;
+ default:
+ events::Audio().Dispatch(audio::StepDownVolume{});
+ break;
}
}
diff --git a/src/input/lvgl_input_driver.cpp b/src/input/lvgl_input_driver.cpp
index 70b6eb5d..9698aa79 100644
--- a/src/input/lvgl_input_driver.cpp
+++ b/src/input/lvgl_input_driver.cpp
@@ -9,12 +9,16 @@
#include <cstdint>
#include <memory>
+#include <variant>
+#include "device_factory.hpp"
#include "feedback_haptics.hpp"
#include "input_touch_wheel.hpp"
+#include "input_trigger.hpp"
#include "input_volume_buttons.hpp"
#include "lvgl.h"
-#include "service_locator.hpp"
+#include "nvs.hpp"
+#include "property.hpp"
[[maybe_unused]] static constexpr char kTag[] = "input";
@@ -32,33 +36,52 @@ static void feedback_cb(lv_indev_drv_t* drv, uint8_t event) {
instance->feedback(event);
}
-LvglInputDriver::LvglInputDriver(
- std::shared_ptr<system_fsm::ServiceLocator> services)
- : services_(services),
+auto intToMode(int raw) -> std::optional<drivers::NvsStorage::InputModes> {
+ switch (raw) {
+ case 0:
+ return drivers::NvsStorage::InputModes::kButtonsOnly;
+ case 1:
+ return drivers::NvsStorage::InputModes::kButtonsWithWheel;
+ case 2:
+ return drivers::NvsStorage::InputModes::kDirectionalWheel;
+ case 3:
+ return drivers::NvsStorage::InputModes::kRotatingWheel;
+ default:
+ return {};
+ }
+}
+
+LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs,
+ DeviceFactory& factory)
+ : nvs_(nvs),
+ factory_(factory),
+ mode_(static_cast<int>(nvs.PrimaryInput()),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ auto mode = intToMode(std::get<int>(val));
+ if (!mode) {
+ return false;
+ }
+ nvs.PrimaryInput(*mode);
+ inputs_ = factory.createInputs(*mode);
+ return true;
+ }),
driver_(),
registration_(nullptr),
- inputs_(),
- feedbacks_(),
+ inputs_(factory.createInputs(nvs.PrimaryInput())),
+ feedbacks_(factory.createFeedbacks()),
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;
+ driver_.long_press_time = kLongPressDelayMs;
+ driver_.long_press_repeat_time = kRepeatDelayMs;
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 {