summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-04-15 14:18:20 +1000
committerjacqueline <me@jacqueline.id.au>2024-04-15 14:18:20 +1000
commit1baaa6dadcea5b8a85f1629e31119f4edba91b75 (patch)
treefeae0c19f1a6744b60f3e59a5d9b8df1c28c6ebf /src
parentc24dfa6846929e8a7659c4aa2633b82494ac7fe1 (diff)
downloadtangara-fw-1baaa6dadcea5b8a85f1629e31119f4edba91b75.tar.gz
Use more generic 'hooks' for each input device's actions
Diffstat (limited to 'src')
-rw-r--r--src/input/CMakeLists.txt3
-rw-r--r--src/input/include/input_hook.hpp47
-rw-r--r--src/input/include/input_hook_actions.hpp28
-rw-r--r--src/input/include/input_nav_buttons.hpp5
-rw-r--r--src/input/include/input_touch_dpad.hpp11
-rw-r--r--src/input/include/input_touch_wheel.hpp10
-rw-r--r--src/input/include/input_volume_buttons.hpp6
-rw-r--r--src/input/input_hook.cpp66
-rw-r--r--src/input/input_hook_actions.cpp52
-rw-r--r--src/input/input_nav_buttons.cpp32
-rw-r--r--src/input/input_touch_dpad.cpp67
-rw-r--r--src/input/input_touch_wheel.cpp56
-rw-r--r--src/input/input_volume_buttons.cpp23
13 files changed, 268 insertions, 138 deletions
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 3bc3e39d..4754ba47 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -5,7 +5,8 @@
idf_component_register(
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"
+ "device_factory.cpp" "input_nav_buttons.cpp" "input_hook.cpp"
+ "input_hook_actions.cpp"
INCLUDE_DIRS "include"
REQUIRES "drivers" "lvgl" "events" "system_fsm")
diff --git a/src/input/include/input_hook.hpp b/src/input/include/input_hook.hpp
new file mode 100644
index 00000000..96b9b5cd
--- /dev/null
+++ b/src/input/include/input_hook.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <functional>
+#include <optional>
+
+#include "hal/lv_hal_indev.h"
+#include "input_trigger.hpp"
+
+namespace input {
+
+using HookCb = std::optional<std::function<void(lv_indev_data_t*)>>;
+
+class Hook {
+ public:
+ Hook(HookCb);
+
+ auto invoke(lv_indev_data_t*) -> void;
+ auto override(HookCb) -> void;
+
+ private:
+ HookCb default_;
+ HookCb override_;
+};
+
+class TriggerHooks {
+ public:
+ TriggerHooks(HookCb cb) : TriggerHooks(cb, cb, cb) {}
+ TriggerHooks(HookCb, HookCb, HookCb);
+
+ auto update(bool, lv_indev_data_t*) -> void;
+ auto override(Trigger::State, HookCb) -> void;
+
+ private:
+ Trigger trigger_;
+
+ Hook click_;
+ Hook long_press_;
+ Hook repeat_;
+};
+
+} // namespace input
diff --git a/src/input/include/input_hook_actions.hpp b/src/input/include/input_hook_actions.hpp
new file mode 100644
index 00000000..a05a14e8
--- /dev/null
+++ b/src/input/include/input_hook_actions.hpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include "hal/lv_hal_indev.h"
+
+namespace input {
+namespace actions {
+
+auto select(lv_indev_data_t*) -> void;
+
+auto scrollUp(lv_indev_data_t*) -> void;
+auto scrollDown(lv_indev_data_t*) -> void;
+
+auto scrollToTop(lv_indev_data_t*) -> void;
+auto scrollToBottom(lv_indev_data_t*) -> void;
+
+auto goBack(lv_indev_data_t*) -> void;
+
+auto volumeUp(lv_indev_data_t*) -> void;
+auto volumeDown(lv_indev_data_t*) -> void;
+
+} // namespace actions
+} // namespace input
diff --git a/src/input/include/input_nav_buttons.hpp b/src/input/include/input_nav_buttons.hpp
index 29a19a16..60566ebc 100644
--- a/src/input/include/input_nav_buttons.hpp
+++ b/src/input/include/input_nav_buttons.hpp
@@ -13,6 +13,7 @@
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_hook.hpp"
#include "input_trigger.hpp"
#include "touchwheel.hpp"
@@ -27,8 +28,8 @@ class NavButtons : public IInputDevice {
private:
drivers::IGpios& gpios_;
- Trigger up_;
- Trigger down_;
+ TriggerHooks up_;
+ TriggerHooks down_;
};
} // namespace input
diff --git a/src/input/include/input_touch_dpad.hpp b/src/input/include/input_touch_dpad.hpp
index 03936acb..f80400dc 100644
--- a/src/input/include/input_touch_dpad.hpp
+++ b/src/input/include/input_touch_dpad.hpp
@@ -6,13 +6,13 @@
#pragma once
-#include <stdint.h>
#include <cstdint>
#include "hal/lv_hal_indev.h"
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_hook.hpp"
#include "input_trigger.hpp"
#include "touchwheel.hpp"
@@ -27,10 +27,11 @@ class TouchDPad : public IInputDevice {
private:
drivers::TouchWheel& wheel_;
- Trigger up_;
- Trigger right_;
- Trigger down_;
- Trigger left_;
+ TriggerHooks centre_;
+ TriggerHooks up_;
+ TriggerHooks right_;
+ TriggerHooks down_;
+ TriggerHooks left_;
};
} // namespace input
diff --git a/src/input/include/input_touch_wheel.hpp b/src/input/include/input_touch_wheel.hpp
index c81cbb1a..88ebee40 100644
--- a/src/input/include/input_touch_wheel.hpp
+++ b/src/input/include/input_touch_wheel.hpp
@@ -13,6 +13,7 @@
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_hook.hpp"
#include "input_trigger.hpp"
#include "nvs.hpp"
#include "property.hpp"
@@ -37,10 +38,11 @@ class TouchWheel : public IInputDevice {
lua::Property sensitivity_;
- Trigger up_;
- Trigger right_;
- Trigger down_;
- Trigger left_;
+ TriggerHooks centre_;
+ TriggerHooks up_;
+ TriggerHooks right_;
+ TriggerHooks down_;
+ TriggerHooks left_;
bool is_scrolling_;
uint8_t threshold_;
diff --git a/src/input/include/input_volume_buttons.hpp b/src/input/include/input_volume_buttons.hpp
index 162ca8d9..68962908 100644
--- a/src/input/include/input_volume_buttons.hpp
+++ b/src/input/include/input_volume_buttons.hpp
@@ -13,7 +13,7 @@
#include "haptics.hpp"
#include "input_device.hpp"
-#include "input_trigger.hpp"
+#include "input_hook.hpp"
#include "touchwheel.hpp"
namespace input {
@@ -27,8 +27,8 @@ class VolumeButtons : public IInputDevice {
private:
drivers::IGpios& gpios_;
- Trigger up_;
- Trigger down_;
+ TriggerHooks up_;
+ TriggerHooks down_;
};
} // namespace input
diff --git a/src/input/input_hook.cpp b/src/input/input_hook.cpp
new file mode 100644
index 00000000..d22a0b7a
--- /dev/null
+++ b/src/input/input_hook.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_hook.hpp"
+
+#include <functional>
+#include <optional>
+#include "hal/lv_hal_indev.h"
+
+namespace input {
+
+Hook::Hook(HookCb fn) : default_(fn), override_() {}
+
+auto Hook::invoke(lv_indev_data_t* d) -> void {
+ if (override_) {
+ std::invoke(*override_, d);
+ } else if (default_) {
+ std::invoke(*default_, d);
+ }
+}
+
+auto Hook::override(HookCb fn) -> void {
+ override_ = fn;
+}
+
+TriggerHooks::TriggerHooks(HookCb click, HookCb long_press, HookCb repeat)
+ : click_(click), long_press_(long_press), repeat_(repeat) {}
+
+auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
+ switch (trigger_.update(pressed)) {
+ case Trigger::State::kClick:
+ click_.invoke(d);
+ break;
+ case Trigger::State::kLongPress:
+ long_press_.invoke(d);
+ break;
+ case Trigger::State::kRepeatPress:
+ repeat_.invoke(d);
+ break;
+ case Trigger::State::kNone:
+ default:
+ break;
+ }
+}
+
+auto TriggerHooks::override(Trigger::State s, HookCb fn) -> void {
+ switch (s) {
+ case Trigger::State::kClick:
+ click_.override(fn);
+ break;
+ case Trigger::State::kLongPress:
+ long_press_.override(fn);
+ break;
+ case Trigger::State::kRepeatPress:
+ repeat_.override(fn);
+ break;
+ case Trigger::State::kNone:
+ default:
+ break;
+ }
+}
+
+} // namespace input
diff --git a/src/input/input_hook_actions.cpp b/src/input/input_hook_actions.cpp
new file mode 100644
index 00000000..0694cccf
--- /dev/null
+++ b/src/input/input_hook_actions.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2024 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input_hook_actions.hpp"
+
+#include <cstdint>
+
+#include "hal/lv_hal_indev.h"
+
+#include "event_queue.hpp"
+#include "ui_events.hpp"
+
+namespace input {
+namespace actions {
+
+auto select(lv_indev_data_t* d) -> void {
+ d->state = LV_INDEV_STATE_PRESSED;
+}
+
+auto scrollUp(lv_indev_data_t* d) -> void {
+ d->enc_diff = -1;
+}
+
+auto scrollDown(lv_indev_data_t* d) -> void {
+ d->enc_diff = 1;
+}
+
+auto scrollToTop(lv_indev_data_t* d) -> void {
+ d->enc_diff = INT16_MIN;
+}
+
+auto scrollToBottom(lv_indev_data_t* d) -> void {
+ d->enc_diff = INT16_MAX;
+}
+
+auto goBack(lv_indev_data_t* d) -> void {
+ events::Ui().Dispatch(ui::internal::BackPressed{});
+}
+
+auto volumeUp(lv_indev_data_t* d) -> void {
+ events::Audio().Dispatch(audio::StepUpVolume{});
+}
+
+auto volumeDown(lv_indev_data_t* d) -> void {
+ events::Audio().Dispatch(audio::StepDownVolume{});
+}
+
+} // namespace actions
+} // namespace input
diff --git a/src/input/input_nav_buttons.cpp b/src/input/input_nav_buttons.cpp
index d83568c8..9db19a2e 100644
--- a/src/input/input_nav_buttons.cpp
+++ b/src/input/input_nav_buttons.cpp
@@ -9,36 +9,18 @@
#include "event_queue.hpp"
#include "gpios.hpp"
#include "hal/lv_hal_indev.h"
+#include "input_hook_actions.hpp"
namespace input {
-NavButtons::NavButtons(drivers::IGpios& gpios) : gpios_(gpios) {}
+NavButtons::NavButtons(drivers::IGpios& gpios)
+ : gpios_(gpios),
+ up_(actions::scrollUp, actions::select, {}),
+ down_(actions::scrollDown, actions::select, {}) {}
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;
- }
+ up_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyUp), data);
+ down_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyDown), data);
}
} // namespace input
diff --git a/src/input/input_touch_dpad.cpp b/src/input/input_touch_dpad.cpp
index 828d6b59..32ca1ac1 100644
--- a/src/input/input_touch_dpad.cpp
+++ b/src/input/input_touch_dpad.cpp
@@ -13,63 +13,42 @@
#include "event_queue.hpp"
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_hook_actions.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) {}
+TouchDPad::TouchDPad(drivers::TouchWheel& wheel)
+ : wheel_(wheel),
+ centre_(actions::select, {}, {}),
+ up_(actions::scrollUp),
+ right_({}, {}, {}),
+ down_(actions::scrollDown),
+ left_(actions::goBack) {}
auto TouchDPad::read(lv_indev_data_t* data) -> void {
wheel_.Update();
auto wheel_data = wheel_.GetTouchWheelData();
- if (wheel_data.is_button_touched) {
- data->state = LV_INDEV_STATE_PRESSED;
- } else {
- data->state = LV_INDEV_STATE_RELEASED;
- }
+ centre_.update(wheel_data.is_button_touched, data);
- 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(
+ up_.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(
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 0, 32),
+ data);
+ right_.update(
+ wheel_data.is_wheel_touched && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 192, 32),
+ data);
+ down_.update(
+ wheel_data.is_wheel_touched && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 128, 32),
+ data);
+ 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;
- }
+ drivers::TouchWheel::isAngleWithin(wheel_data.wheel_position, 64, 32),
+ data);
}
} // namespace input
diff --git a/src/input/input_touch_wheel.cpp b/src/input/input_touch_wheel.cpp
index 7670e342..031c21ef 100644
--- a/src/input/input_touch_wheel.cpp
+++ b/src/input/input_touch_wheel.cpp
@@ -5,16 +5,16 @@
*/
#include "input_touch_wheel.hpp"
-#include <stdint.h>
#include <cstdint>
#include <variant>
-#include "event_queue.hpp"
#include "hal/lv_hal_indev.h"
+#include "event_queue.hpp"
#include "haptics.hpp"
#include "input_device.hpp"
+#include "input_hook_actions.hpp"
#include "input_trigger.hpp"
#include "nvs.hpp"
#include "property.hpp"
@@ -39,6 +39,11 @@ TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
threshold_ = calculateThreshold(int_val);
return true;
}),
+ centre_(actions::select, {}, {}),
+ up_({}, actions::scrollToTop, actions::scrollUp),
+ right_({}, {}, {}),
+ down_({}, actions::scrollToBottom, actions::scrollDown),
+ left_({}, actions::goBack, {}),
is_scrolling_(false),
threshold_(calculateThreshold(nvs.ScrollSensitivity())),
is_first_read_(true),
@@ -63,45 +68,24 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void {
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;
- }
+ centre_.update(!is_scrolling_ && wheel_data.is_button_touched, data);
// 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;
- }
+ up_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 0, 32),
+ data);
+ right_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 192, 32),
+ data);
+ down_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 128, 32),
+ data);
+ left_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 64, 32),
+ data);
}
auto TouchWheel::sensitivity() -> lua::Property& {
diff --git a/src/input/input_volume_buttons.cpp b/src/input/input_volume_buttons.cpp
index 0413222c..bc04cd66 100644
--- a/src/input/input_volume_buttons.cpp
+++ b/src/input/input_volume_buttons.cpp
@@ -7,29 +7,16 @@
#include "input_volume_buttons.hpp"
#include "event_queue.hpp"
#include "gpios.hpp"
+#include "input_hook_actions.hpp"
namespace input {
-VolumeButtons::VolumeButtons(drivers::IGpios& gpios) : gpios_(gpios) {}
+VolumeButtons::VolumeButtons(drivers::IGpios& gpios)
+ : gpios_(gpios), up_(actions::volumeUp), down_(actions::volumeDown) {}
auto VolumeButtons::read(lv_indev_data_t* data) -> void {
- bool vol_up = gpios_.Get(drivers::IGpios::Pin::kKeyUp);
- 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);
- switch (down_.update(!vol_down)) {
- case Trigger::State::kNone:
- break;
- default:
- events::Audio().Dispatch(audio::StepDownVolume{});
- break;
- }
+ up_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyUp), data);
+ down_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyDown), data);
}
} // namespace input