summaryrefslogtreecommitdiff
path: root/src/tangara/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/tangara/input')
-rw-r--r--src/tangara/input/device_factory.cpp17
-rw-r--r--src/tangara/input/input_hook_actions.cpp6
-rw-r--r--src/tangara/input/input_hook_actions.hpp2
-rw-r--r--src/tangara/input/input_touch_wheel.cpp66
-rw-r--r--src/tangara/input/input_touch_wheel.hpp8
-rw-r--r--src/tangara/input/lvgl_input_driver.cpp2
6 files changed, 84 insertions, 17 deletions
diff --git a/src/tangara/input/device_factory.cpp b/src/tangara/input/device_factory.cpp
index ff597556..9ae69e47 100644
--- a/src/tangara/input/device_factory.cpp
+++ b/src/tangara/input/device_factory.cpp
@@ -25,7 +25,11 @@ DeviceFactory::DeviceFactory(
: services_(services) {
if (services->touchwheel()) {
wheel_ =
- std::make_shared<TouchWheel>(services->nvs(), **services->touchwheel());
+ std::make_shared<TouchWheel>(services->nvs(), **services->touchwheel(), services->track_queue());
+ auto wheel_mode = services_->nvs().WheelInput();
+ if (wheel_mode == drivers::NvsStorage::WheelInputModes::kWheelWithButtons) {
+ wheel_->activate_buttons(true);
+ }
}
reset_ = std::make_shared<HardReset>(services_->gpios());
}
@@ -73,6 +77,17 @@ auto DeviceFactory::createInputs()
}
break;
case drivers::NvsStorage::WheelInputModes::kRotatingWheel:
+ if (wheel_) {
+ wheel_->activate_buttons(false);
+ ret.push_back(wheel_);
+ }
+ break;
+ case drivers::NvsStorage::WheelInputModes::kWheelWithButtons:
+ if (wheel_) {
+ wheel_->activate_buttons(true);
+ ret.push_back(wheel_);
+ }
+ break;
default: // Don't break input over a bad enum value.
if (wheel_) {
ret.push_back(wheel_);
diff --git a/src/tangara/input/input_hook_actions.cpp b/src/tangara/input/input_hook_actions.cpp
index 001d3fb0..587683ba 100644
--- a/src/tangara/input/input_hook_actions.cpp
+++ b/src/tangara/input/input_hook_actions.cpp
@@ -68,6 +68,12 @@ auto nextTrack(audio::TrackQueue& queue) -> HookCallback {
}};
}
+auto skipBack() -> HookCallback {
+ return HookCallback{.name = "skip_back", .fn = [&](lv_indev_data_t* d) {
+ events::Ui().Dispatch(ui::SeekBack{.seconds = 25});
+ }};
+}
+
auto prevTrack(audio::TrackQueue& queue) -> HookCallback {
return HookCallback{.name = "prev_track", .fn = [&](lv_indev_data_t* d) {
queue.previous();
diff --git a/src/tangara/input/input_hook_actions.hpp b/src/tangara/input/input_hook_actions.hpp
index 2db0b6e7..67902924 100644
--- a/src/tangara/input/input_hook_actions.hpp
+++ b/src/tangara/input/input_hook_actions.hpp
@@ -27,6 +27,8 @@ auto togglePlayPause() -> HookCallback;
auto nextTrack(audio::TrackQueue& queue) -> HookCallback;
auto prevTrack(audio::TrackQueue& queue) -> HookCallback;
+auto skipBack() -> HookCallback;
+
auto volumeUp() -> HookCallback;
auto volumeDown() -> HookCallback;
diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp
index ae192e31..0a8bab48 100644
--- a/src/tangara/input/input_touch_wheel.cpp
+++ b/src/tangara/input/input_touch_wheel.cpp
@@ -25,9 +25,12 @@
namespace input {
-TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
+TouchWheel::TouchWheel(drivers::NvsStorage& nvs,
+ drivers::TouchWheel& wheel,
+ audio::TrackQueue& queue)
: nvs_(nvs),
wheel_(wheel),
+ queue_(queue),
sensitivity_(static_cast<int>(nvs.ScrollSensitivity()),
[&](const lua::LuaValue& val) {
if (!std::holds_alternative<int>(val)) {
@@ -55,7 +58,23 @@ TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
threshold_(calculateThreshold(nvs.ScrollSensitivity())),
is_first_read_(true),
last_angle_(0),
- last_wheel_touch_time_(0) {}
+ last_wheel_touch_time_(0),
+ buttons_active_(false) {}
+
+auto TouchWheel::activate_buttons(bool activate) -> void {
+ if (activate) {
+ up_.override(Trigger::State::kClick, {actions::skipBack()});
+ left_.override(Trigger::State::kClick, {actions::prevTrack(queue_)});
+ right_.override(Trigger::State::kClick, {actions::nextTrack(queue_)});
+ down_.override(Trigger::State::kClick, {actions::togglePlayPause()});
+ } else {
+ up_.override(Trigger::State::kClick, std::nullopt);
+ left_.override(Trigger::State::kClick, std::nullopt);
+ right_.override(Trigger::State::kClick, std::nullopt);
+ down_.override(Trigger::State::kClick, std::nullopt);
+ }
+ buttons_active_ = activate;
+}
auto TouchWheel::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
if (locked_) {
@@ -99,25 +118,42 @@ auto TouchWheel::read(lv_indev_data_t* data, std::vector<InputEvent>& events) ->
// If the user is touching the wheel but not scrolling, then they may be
// clicking on one of the wheel's cardinal directions.
+ const uint64_t now_us = esp_timer_get_time() / 1000;
if (is_scrolling_) {
up_.cancel();
right_.cancel();
down_.cancel();
left_.cancel();
+ last_scroll_ = now_us;
} else {
- bool pressing = wheel_data.is_wheel_touched;
- 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);
+ const auto time_since_last_scroll = last_scroll_ - now_us;
+ bool pressing = wheel_data.is_wheel_touched &&
+ (time_since_last_scroll > SCROLL_TIMEOUT_US);
+
+ const auto ustate =
+ up_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 0, 32),
+ data);
+ const auto rstate =
+ right_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 192, 32),
+ data);
+ const auto dstate =
+ down_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 128, 32),
+ data);
+ const auto lstate =
+ left_.update(pressing && drivers::TouchWheel::isAngleWithin(
+ wheel_data.wheel_position, 64, 32),
+ data);
+
+ // This is for haptic feedback.
+ if (buttons_active_ &&
+ (ustate == Trigger::State::kClick || rstate == Trigger::State::kClick ||
+ dstate == Trigger::State::kClick ||
+ lstate == Trigger::State::kClick)) {
+ events.push_back(InputEvent::kOnPress);
+ }
}
}
diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp
index 3f2ed49e..9c9135b4 100644
--- a/src/tangara/input/input_touch_wheel.hpp
+++ b/src/tangara/input/input_touch_wheel.hpp
@@ -23,7 +23,7 @@ namespace input {
class TouchWheel : public IInputDevice {
public:
- TouchWheel(drivers::NvsStorage&, drivers::TouchWheel&);
+ TouchWheel(drivers::NvsStorage&, drivers::TouchWheel&, audio::TrackQueue&);
auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
@@ -35,6 +35,8 @@ class TouchWheel : public IInputDevice {
auto sensitivity() -> lua::Property&;
+ auto activate_buttons(bool activate) -> void;
+
private:
const int64_t SCROLL_TIMEOUT_US = 250000; // 250ms
@@ -44,6 +46,8 @@ class TouchWheel : public IInputDevice {
drivers::NvsStorage& nvs_;
drivers::TouchWheel& wheel_;
+ audio::TrackQueue& queue_;
+
lua::Property sensitivity_;
TriggerHooks centre_;
@@ -54,10 +58,12 @@ class TouchWheel : public IInputDevice {
bool locked_;
bool is_scrolling_;
+ uint64_t last_scroll_;
uint8_t threshold_;
bool is_first_read_;
uint8_t last_angle_;
int64_t last_wheel_touch_time_;
+ bool buttons_active_;
};
} // namespace input
diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp
index b4bab365..00cc2b81 100644
--- a/src/tangara/input/lvgl_input_driver.cpp
+++ b/src/tangara/input/lvgl_input_driver.cpp
@@ -64,6 +64,8 @@ auto intToWheelMode(int raw)
return drivers::NvsStorage::WheelInputModes::kDirectionalWheel;
case 2:
return drivers::NvsStorage::WheelInputModes::kRotatingWheel;
+ case 3:
+ return drivers::NvsStorage::WheelInputModes::kWheelWithButtons;
default:
return {};
}