summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorailurux <ailuruxx@gmail.com>2025-02-07 02:44:24 +0000
committercooljqln <cooljqln@noreply.codeberg.org>2025-02-07 02:44:24 +0000
commit48495ddafe2ed59611c9491470f192b790e6146d (patch)
tree7e044de2e8d2882078bf783631ffb668a84ca376 /src
parent275b931e0bb2ad32986b234e7a22c237d8edb831 (diff)
downloadtangara-fw-48495ddafe2ed59611c9491470f192b790e6146d.tar.gz
Add centre button haptic feedback on touch, and setting to disable/lessen haptics (#246)
This adds a way for feedback devices to respond to events from outside of LVGL's event system, being passed from input device to feedback device through a vector. This was done so that touch events and long-press triggers can now give feedback through haptics. This PR also adds haptic modes, saved in nvs similarly to input and locked input modes, to disable or change the haptic effect behaviour based on which mode is selected. Finally, this also fixes a bug in which some click events would not trigger haptics, at the expense of re-introducing the (undesired?) behaviour of clicking a button that transitions to a new screen causing a double click. Relevant issues this should close: #195, #233, and (partially?) #120 Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/246 Co-authored-by: ailurux <ailuruxx@gmail.com> Co-committed-by: ailurux <ailuruxx@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/drivers/include/drivers/nvs.hpp10
-rw-r--r--src/drivers/nvs.cpp29
-rw-r--r--src/tangara/input/device_factory.cpp2
-rw-r--r--src/tangara/input/feedback_device.hpp2
-rw-r--r--src/tangara/input/feedback_haptics.cpp53
-rw-r--r--src/tangara/input/feedback_haptics.hpp8
-rw-r--r--src/tangara/input/feedback_tts.cpp6
-rw-r--r--src/tangara/input/feedback_tts.hpp1
-rw-r--r--src/tangara/input/input_device.hpp3
-rw-r--r--src/tangara/input/input_events.hpp18
-rw-r--r--src/tangara/input/input_hard_reset.cpp2
-rw-r--r--src/tangara/input/input_hard_reset.hpp2
-rw-r--r--src/tangara/input/input_hook.cpp6
-rw-r--r--src/tangara/input/input_hook.hpp2
-rw-r--r--src/tangara/input/input_nav_buttons.cpp2
-rw-r--r--src/tangara/input/input_nav_buttons.hpp2
-rw-r--r--src/tangara/input/input_touch_dpad.cpp2
-rw-r--r--src/tangara/input/input_touch_dpad.hpp2
-rw-r--r--src/tangara/input/input_touch_wheel.cpp9
-rw-r--r--src/tangara/input/input_touch_wheel.hpp2
-rw-r--r--src/tangara/input/input_trigger.cpp2
-rw-r--r--src/tangara/input/input_trigger.hpp1
-rw-r--r--src/tangara/input/input_volume_buttons.cpp2
-rw-r--r--src/tangara/input/input_volume_buttons.hpp2
-rw-r--r--src/tangara/input/lvgl_input_driver.cpp17
-rw-r--r--src/tangara/input/lvgl_input_driver.hpp2
-rw-r--r--src/tangara/lua/lua_controls.cpp20
-rw-r--r--src/tangara/ui/ui_fsm.cpp1
28 files changed, 186 insertions, 24 deletions
diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp
index 18bc5de6..e3a105f8 100644
--- a/src/drivers/include/drivers/nvs.hpp
+++ b/src/drivers/include/drivers/nvs.hpp
@@ -110,6 +110,15 @@ class NvsStorage {
auto OutputMode() -> Output;
auto OutputMode(Output) -> void;
+ enum class HapticsModes : uint8_t {
+ kDisabled = 0,
+ kMinimal = 1,
+ kStrong = 2,
+ };
+ auto HapticsMode() -> HapticsModes;
+ auto HapticsMode(HapticsModes) -> void;
+ static auto intToHapticsMode(int raw) -> HapticsModes;
+
auto ScreenBrightness() -> uint_fast8_t;
auto ScreenBrightness(uint_fast8_t) -> void;
@@ -177,6 +186,7 @@ class NvsStorage {
Setting<uint8_t> input_mode_;
Setting<uint8_t> locked_input_mode_;
Setting<uint8_t> output_mode_;
+ Setting<uint8_t> haptics_mode_;
Setting<std::string> theme_;
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index 02a0058b..04a93fd9 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -35,6 +35,7 @@ static constexpr char kKeyAmpCurrentVolume[] = "hp_vol";
static constexpr char kKeyAmpLeftBias[] = "hp_bias";
static constexpr char kKeyPrimaryInput[] = "in_pri";
static constexpr char kKeyLockedInput[] = "in_locked";
+static constexpr char kKeyHaptics[] = "haptic_mode";
static constexpr char kKeyScrollSensitivity[] = "scroll";
static constexpr char kKeyLockPolarity[] = "lockpol";
static constexpr char kKeyDisplayCols[] = "dispcols";
@@ -275,6 +276,7 @@ NvsStorage::NvsStorage(nvs_handle_t handle)
input_mode_(kKeyPrimaryInput),
locked_input_mode_(kKeyLockedInput),
output_mode_(kKeyOutput),
+ haptics_mode_(kKeyHaptics),
theme_{kKeyInterfaceTheme},
bt_preferred_(kKeyBluetoothPreferred),
bt_names_(kKeyBluetoothNames),
@@ -304,6 +306,7 @@ auto NvsStorage::Read() -> void {
input_mode_.read(handle_);
locked_input_mode_.read(handle_);
output_mode_.read(handle_);
+ haptics_mode_.read(handle_);
theme_.read(handle_);
bt_preferred_.read(handle_);
bt_names_.read(handle_);
@@ -328,6 +331,7 @@ auto NvsStorage::Write() -> bool {
input_mode_.write(handle_);
locked_input_mode_.write(handle_);
output_mode_.write(handle_);
+ haptics_mode_.write(handle_);
theme_.write(handle_);
bt_preferred_.write(handle_);
bt_names_.write(handle_);
@@ -483,6 +487,31 @@ auto NvsStorage::OutputMode(Output out) -> void {
nvs_commit(handle_);
}
+auto NvsStorage::HapticsMode() -> HapticsModes {
+ std::lock_guard<std::mutex> lock{mutex_};
+ int val = haptics_mode_.get().value_or(static_cast<uint8_t>(HapticsModes::kMinimal));
+ return intToHapticsMode(val);
+}
+
+auto NvsStorage::intToHapticsMode(int raw) -> HapticsModes {
+ switch (raw) {
+ case static_cast<int>(HapticsModes::kDisabled):
+ return HapticsModes::kDisabled;
+ case static_cast<int>(HapticsModes::kMinimal):
+ return HapticsModes::kMinimal;
+ case static_cast<int>(HapticsModes::kStrong):
+ return HapticsModes::kStrong;
+ default:
+ return HapticsModes::kStrong;
+ }
+}
+
+auto NvsStorage::HapticsMode(HapticsModes mode) -> void {
+ std::lock_guard<std::mutex> lock{mutex_};
+ haptics_mode_.set(static_cast<uint8_t>(mode));
+}
+
+
auto NvsStorage::FastCharge() -> bool {
std::lock_guard<std::mutex> lock{mutex_};
return fast_charge_.get().value_or(true);
diff --git a/src/tangara/input/device_factory.cpp b/src/tangara/input/device_factory.cpp
index 22df4ebe..fe2e2485 100644
--- a/src/tangara/input/device_factory.cpp
+++ b/src/tangara/input/device_factory.cpp
@@ -56,7 +56,7 @@ auto DeviceFactory::createInputs(drivers::NvsStorage::InputModes mode)
auto DeviceFactory::createFeedbacks()
-> std::vector<std::shared_ptr<IFeedbackDevice>> {
return {
- std::make_shared<Haptics>(services_->haptics()),
+ std::make_shared<Haptics>(services_->haptics(), services_),
std::make_shared<TextToSpeech>(services_->tts()),
};
}
diff --git a/src/tangara/input/feedback_device.hpp b/src/tangara/input/feedback_device.hpp
index 8253642f..31ad1fb1 100644
--- a/src/tangara/input/feedback_device.hpp
+++ b/src/tangara/input/feedback_device.hpp
@@ -8,6 +8,7 @@
#include <cstdint>
#include "core/lv_group.h"
+#include "input/input_events.hpp"
namespace input {
@@ -25,6 +26,7 @@ class IFeedbackDevice {
virtual ~IFeedbackDevice() {}
virtual auto feedback(lv_group_t* group, uint8_t event_type) -> void = 0;
+ virtual auto feedback(lv_group_t* group, InputEvent event) -> void = 0;
// TODO: Add configuration; likely the same shape of interface that
// IInputDevice uses.
diff --git a/src/tangara/input/feedback_haptics.cpp b/src/tangara/input/feedback_haptics.cpp
index a447a69d..fb203915 100644
--- a/src/tangara/input/feedback_haptics.cpp
+++ b/src/tangara/input/feedback_haptics.cpp
@@ -18,21 +18,64 @@ namespace input {
using Effect = drivers::Haptics::Effect;
-Haptics::Haptics(drivers::Haptics& haptics_) : haptics_(haptics_) {}
+Haptics::Haptics(drivers::Haptics& haptics_,
+ std::shared_ptr<system_fsm::ServiceLocator> services)
+ : haptics_(haptics_), services_(services) {}
auto Haptics::feedback(lv_group_t* group, uint8_t event_type) -> void {
lv_obj_t* obj = lv_group_get_focused(group);
- if (obj == last_selection_) {
+
+ auto haptics_mode = services_->nvs().HapticsMode();
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kDisabled ) {
return;
}
- last_selection_ = obj;
switch (event_type) {
case LV_EVENT_FOCUSED:
- haptics_.PlayWaveformEffect(Effect::kMediumClick1_100Pct);
+ if (obj == last_selection_) {
+ return;
+ }
+ last_selection_ = obj;
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kMinimal) {
+ haptics_.PlayWaveformEffect(Effect::kStrongClick_30Pct);
+ } else {
+ haptics_.PlayWaveformEffect(Effect::kMediumClick1_100Pct);
+ }
break;
case LV_EVENT_CLICKED:
- haptics_.PlayWaveformEffect(Effect::kSharpClick_100Pct);
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kMinimal) {
+ haptics_.PlayWaveformEffect(Effect::kSharpClick_30Pct);
+ } else {
+ haptics_.PlayWaveformEffect(Effect::kSharpClick_100Pct);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+auto Haptics::feedback(lv_group_t* group, InputEvent event) -> void {
+ lv_obj_t* obj = lv_group_get_focused(group);
+
+ auto haptics_mode = services_->nvs().HapticsMode();
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kDisabled) {
+ return;
+ }
+
+ switch (event) {
+ case InputEvent::kOnPress:
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kMinimal) {
+ haptics_.PlayWaveformEffect(Effect::kSoftBump_30Pct);
+ } else {
+ haptics_.PlayWaveformEffect(Effect::kSharpTick2_80Pct);
+ }
+ break;
+ case InputEvent::kOnLongPress:
+ if (haptics_mode == drivers::NvsStorage::HapticsModes::kMinimal) {
+ haptics_.PlayWaveformEffect(Effect::kShortDoubleClickStrong4_30Pct);
+ } else {
+ haptics_.PlayWaveformEffect(Effect::kShortDoubleSharpTick3_60Pct);
+ }
break;
default:
break;
diff --git a/src/tangara/input/feedback_haptics.hpp b/src/tangara/input/feedback_haptics.hpp
index 91d7ec3a..90ed5ff2 100644
--- a/src/tangara/input/feedback_haptics.hpp
+++ b/src/tangara/input/feedback_haptics.hpp
@@ -12,17 +12,23 @@
#include "drivers/haptics.hpp"
#include "input/feedback_device.hpp"
+#include "input/input_events.hpp"
+#include "drivers/nvs.hpp"
+#include "system_fsm/service_locator.hpp"
namespace input {
class Haptics : public IFeedbackDevice {
public:
- Haptics(drivers::Haptics& haptics_);
+ Haptics(drivers::Haptics& haptics_,
+ std::shared_ptr<system_fsm::ServiceLocator> services);
auto feedback(lv_group_t*, uint8_t event_type) -> void override;
+ auto feedback(lv_group_t*, InputEvent event) -> void override;
private:
drivers::Haptics& haptics_;
+ std::shared_ptr<system_fsm::ServiceLocator> services_;
lv_obj_t* last_selection_;
};
diff --git a/src/tangara/input/feedback_tts.cpp b/src/tangara/input/feedback_tts.cpp
index e7e167c6..04c2830d 100644
--- a/src/tangara/input/feedback_tts.cpp
+++ b/src/tangara/input/feedback_tts.cpp
@@ -22,6 +22,7 @@
#include "tts/events.hpp"
#include "tts/provider.hpp"
+#include "feedback_tts.hpp"
namespace input {
@@ -50,6 +51,10 @@ auto TextToSpeech::feedback(lv_group_t* group, uint8_t event_type) -> void {
}
}
+auto TextToSpeech::feedback(lv_group_t*, InputEvent event) -> void {
+ return;
+}
+
auto TextToSpeech::describe(lv_obj_t& obj) -> void {
if (lv_obj_check_type(&obj, &lv_button_class) ||
lv_obj_check_type(&obj, &lv_list_button_class)) {
@@ -94,4 +99,5 @@ auto TextToSpeech::findDescription(lv_obj_t& obj)
return {};
}
+
} // namespace input
diff --git a/src/tangara/input/feedback_tts.hpp b/src/tangara/input/feedback_tts.hpp
index ddd83ff0..00fbf06d 100644
--- a/src/tangara/input/feedback_tts.hpp
+++ b/src/tangara/input/feedback_tts.hpp
@@ -22,6 +22,7 @@ class TextToSpeech : public IFeedbackDevice {
TextToSpeech(tts::Provider&);
auto feedback(lv_group_t*, uint8_t event_type) -> void override;
+ auto feedback(lv_group_t*, InputEvent event) -> void override;
private:
tts::Provider& tts_;
diff --git a/src/tangara/input/input_device.hpp b/src/tangara/input/input_device.hpp
index 424c0da3..7b8d993d 100644
--- a/src/tangara/input/input_device.hpp
+++ b/src/tangara/input/input_device.hpp
@@ -12,6 +12,7 @@
#include "drivers/nvs.hpp"
#include "indev/lv_indev.h"
+#include "input/input_events.hpp"
#include "input/input_hook.hpp"
#include "lua/property.hpp"
@@ -27,7 +28,7 @@ class IInputDevice {
public:
virtual ~IInputDevice() {}
- virtual auto read(lv_indev_data_t* data) -> void = 0;
+ virtual auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void = 0;
virtual auto name() -> std::string = 0;
virtual auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> {
diff --git a/src/tangara/input/input_events.hpp b/src/tangara/input/input_events.hpp
new file mode 100644
index 00000000..e9826c67
--- /dev/null
+++ b/src/tangara/input/input_events.hpp
@@ -0,0 +1,18 @@
+
+/*
+ * Copyright 2025 ailurux <ailuruxx@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+namespace input {
+
+enum class InputEvent {
+ kNone = 0,
+ kOnPress = 1,
+ kOnLongPress = 2,
+};
+
+} // namespace input \ No newline at end of file
diff --git a/src/tangara/input/input_hard_reset.cpp b/src/tangara/input/input_hard_reset.cpp
index 7fcca3eb..44de500c 100644
--- a/src/tangara/input/input_hard_reset.cpp
+++ b/src/tangara/input/input_hard_reset.cpp
@@ -14,7 +14,7 @@ namespace input {
HardReset::HardReset(drivers::IGpios& gpios) : gpios_(gpios) {}
-auto HardReset::read(lv_indev_data_t* data) -> void {
+auto HardReset::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
bool buttons_pressed = !gpios_.Get(drivers::IGpios::Pin::kKeyUp) &&
!gpios_.Get(drivers::IGpios::Pin::kKeyDown);
if (!buttons_pressed) {
diff --git a/src/tangara/input/input_hard_reset.hpp b/src/tangara/input/input_hard_reset.hpp
index 00f218bf..93be56c5 100644
--- a/src/tangara/input/input_hard_reset.hpp
+++ b/src/tangara/input/input_hard_reset.hpp
@@ -20,7 +20,7 @@ class HardReset : public IInputDevice {
public:
HardReset(drivers::IGpios&);
- auto read(lv_indev_data_t* data) -> void override;
+ auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
diff --git a/src/tangara/input/input_hook.cpp b/src/tangara/input/input_hook.cpp
index 0867bb39..9be1be7c 100644
--- a/src/tangara/input/input_hook.cpp
+++ b/src/tangara/input/input_hook.cpp
@@ -50,8 +50,9 @@ TriggerHooks::TriggerHooks(std::string name,
long_press_("long_press", long_press),
repeat_("repeat", repeat) {}
-auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
- switch (trigger_.update(pressed)) {
+auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> Trigger::State {
+ auto state = trigger_.update(pressed);
+ switch (state) {
case Trigger::State::kClick:
click_.invoke(d);
break;
@@ -68,6 +69,7 @@ auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
default:
break;
}
+ return state;
}
auto TriggerHooks::override(Trigger::State s, std::optional<HookCallback> cb)
diff --git a/src/tangara/input/input_hook.hpp b/src/tangara/input/input_hook.hpp
index 94a35850..67122e1f 100644
--- a/src/tangara/input/input_hook.hpp
+++ b/src/tangara/input/input_hook.hpp
@@ -52,7 +52,7 @@ class TriggerHooks {
std::optional<HookCallback> long_press,
std::optional<HookCallback> repeat);
- auto update(bool, lv_indev_data_t*) -> void;
+ auto update(bool, lv_indev_data_t*) -> Trigger::State;
auto override(Trigger::State, std::optional<HookCallback>) -> void;
auto name() const -> const std::string&;
diff --git a/src/tangara/input/input_nav_buttons.cpp b/src/tangara/input/input_nav_buttons.cpp
index a5e10013..ede6b714 100644
--- a/src/tangara/input/input_nav_buttons.cpp
+++ b/src/tangara/input/input_nav_buttons.cpp
@@ -20,7 +20,7 @@ NavButtons::NavButtons(drivers::IGpios& gpios)
down_("lower", {}, actions::scrollDown(), actions::select(), {}),
locked_(false) {}
-auto NavButtons::read(lv_indev_data_t* data) -> void {
+auto NavButtons::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
bool up = !gpios_.Get(drivers::IGpios::Pin::kKeyUp);
bool down = !gpios_.Get(drivers::IGpios::Pin::kKeyDown);
diff --git a/src/tangara/input/input_nav_buttons.hpp b/src/tangara/input/input_nav_buttons.hpp
index c9575fe0..c28cce91 100644
--- a/src/tangara/input/input_nav_buttons.hpp
+++ b/src/tangara/input/input_nav_buttons.hpp
@@ -23,7 +23,7 @@ class NavButtons : public IInputDevice {
public:
NavButtons(drivers::IGpios&);
- auto read(lv_indev_data_t* data) -> void override;
+ auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
diff --git a/src/tangara/input/input_touch_dpad.cpp b/src/tangara/input/input_touch_dpad.cpp
index 25c2315b..c866f37c 100644
--- a/src/tangara/input/input_touch_dpad.cpp
+++ b/src/tangara/input/input_touch_dpad.cpp
@@ -28,7 +28,7 @@ TouchDPad::TouchDPad(drivers::TouchWheel& wheel)
left_("left", actions::goBack(), {}, {}, {}),
locked_(false) {}
-auto TouchDPad::read(lv_indev_data_t* data) -> void {
+auto TouchDPad::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
if (locked_) {
return;
}
diff --git a/src/tangara/input/input_touch_dpad.hpp b/src/tangara/input/input_touch_dpad.hpp
index 086f556e..82de26bf 100644
--- a/src/tangara/input/input_touch_dpad.hpp
+++ b/src/tangara/input/input_touch_dpad.hpp
@@ -22,7 +22,7 @@ class TouchDPad : public IInputDevice {
public:
TouchDPad(drivers::TouchWheel&);
- auto read(lv_indev_data_t* data) -> void override;
+ auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp
index 1aee6fae..29153396 100644
--- a/src/tangara/input/input_touch_wheel.cpp
+++ b/src/tangara/input/input_touch_wheel.cpp
@@ -57,7 +57,7 @@ TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
last_angle_(0),
last_wheel_touch_time_(0) {}
-auto TouchWheel::read(lv_indev_data_t* data) -> void {
+auto TouchWheel::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
if (locked_) {
return;
}
@@ -88,9 +88,14 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void {
bool wheel_touch_timed_out =
esp_timer_get_time() - last_wheel_touch_time_ > SCROLL_TIMEOUT_US;
- centre_.update(wheel_touch_timed_out && wheel_data.is_button_touched &&
+ auto centre_state = centre_.update(wheel_touch_timed_out && wheel_data.is_button_touched &&
!wheel_data.is_wheel_touched,
data);
+ if (centre_state == input::Trigger::State::kPress) {
+ events.push_back(InputEvent::kOnPress);
+ } else if (centre_state == input::Trigger::State::kLongPress) {
+ events.push_back(InputEvent::kOnLongPress);
+ }
// If the user is touching the wheel but not scrolling, then they may be
// clicking on one of the wheel's cardinal directions.
diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp
index 420454b8..b2583e85 100644
--- a/src/tangara/input/input_touch_wheel.hpp
+++ b/src/tangara/input/input_touch_wheel.hpp
@@ -25,7 +25,7 @@ class TouchWheel : public IInputDevice {
public:
TouchWheel(drivers::NvsStorage&, drivers::TouchWheel&);
- auto read(lv_indev_data_t* data) -> void override;
+ auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
diff --git a/src/tangara/input/input_trigger.cpp b/src/tangara/input/input_trigger.cpp
index eb67bcca..6c97f08c 100644
--- a/src/tangara/input/input_trigger.cpp
+++ b/src/tangara/input/input_trigger.cpp
@@ -44,7 +44,7 @@ auto Trigger::update(bool is_pressed) -> State {
was_double_click_ = false;
times_long_pressed_ = 0;
was_pressed_ = true;
- return State::kNone;
+ return State::kPress;
}
// The key was released. If there were no long-press events fired during the
diff --git a/src/tangara/input/input_trigger.hpp b/src/tangara/input/input_trigger.hpp
index 9f0b7e19..5bf8e13c 100644
--- a/src/tangara/input/input_trigger.hpp
+++ b/src/tangara/input/input_trigger.hpp
@@ -23,6 +23,7 @@ class Trigger {
kDoubleClick,
kLongPress,
kRepeatPress,
+ kPress
};
Trigger();
diff --git a/src/tangara/input/input_volume_buttons.cpp b/src/tangara/input/input_volume_buttons.cpp
index 5c814ffa..ffeea18f 100644
--- a/src/tangara/input/input_volume_buttons.cpp
+++ b/src/tangara/input/input_volume_buttons.cpp
@@ -17,7 +17,7 @@ VolumeButtons::VolumeButtons(drivers::IGpios& gpios)
down_("lower", actions::volumeDown()),
locked_() {}
-auto VolumeButtons::read(lv_indev_data_t* data) -> void {
+auto VolumeButtons::read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void {
bool up = !gpios_.Get(drivers::IGpios::Pin::kKeyUp);
bool down = !gpios_.Get(drivers::IGpios::Pin::kKeyDown);
diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp
index 35a44390..17f60d7e 100644
--- a/src/tangara/input/input_volume_buttons.hpp
+++ b/src/tangara/input/input_volume_buttons.hpp
@@ -22,7 +22,7 @@ class VolumeButtons : public IInputDevice {
public:
VolumeButtons(drivers::IGpios&);
- auto read(lv_indev_data_t* data) -> void override;
+ auto read(lv_indev_data_t* data, std::vector<InputEvent>& events) -> void override;
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp
index 2859c6a8..03d5cbb7 100644
--- a/src/tangara/input/lvgl_input_driver.cpp
+++ b/src/tangara/input/lvgl_input_driver.cpp
@@ -112,6 +112,15 @@ LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs,
nvs.LockedInput(*mode);
return true;
}),
+ haptics_mode_(static_cast<int>(nvs.HapticsMode()),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ auto mode = drivers::NvsStorage::intToHapticsMode(std::get<int>(val));
+ nvs.HapticsMode(mode);
+ return true;
+ }),
inputs_(factory.createInputs(nvs.PrimaryInput())),
feedbacks_(factory.createFeedbacks()),
is_locked_(false) {
@@ -141,8 +150,14 @@ auto LvglInputDriver::setGroup(lv_group_t* g) -> void {
}
auto LvglInputDriver::read(lv_indev_data_t* data) -> void {
+ std::vector<InputEvent> events;
for (auto&& device : inputs_) {
- device->read(data);
+ device->read(data, events);
+ }
+ for (auto event: events) {
+ for (auto&& device : feedbacks_) {
+ device->feedback(lv_indev_get_group(device_), event);
+ }
}
}
diff --git a/src/tangara/input/lvgl_input_driver.hpp b/src/tangara/input/lvgl_input_driver.hpp
index ce950621..629a0a78 100644
--- a/src/tangara/input/lvgl_input_driver.hpp
+++ b/src/tangara/input/lvgl_input_driver.hpp
@@ -37,6 +37,7 @@ class LvglInputDriver {
auto mode() -> lua::Property& { return mode_; }
auto lockedMode() -> lua::Property& { return locked_mode_; }
+ auto hapticsMode() -> lua::Property& { return haptics_mode_; }
auto setGroup(lv_group_t*) -> void;
auto read(lv_indev_data_t* data) -> void;
@@ -51,6 +52,7 @@ class LvglInputDriver {
lua::Property mode_;
lua::Property locked_mode_;
+ lua::Property haptics_mode_;
lv_indev_t* device_;
std::vector<std::shared_ptr<IInputDevice>> inputs_;
diff --git a/src/tangara/lua/lua_controls.cpp b/src/tangara/lua/lua_controls.cpp
index 87b7ca16..bc2588ac 100644
--- a/src/tangara/lua/lua_controls.cpp
+++ b/src/tangara/lua/lua_controls.cpp
@@ -58,8 +58,28 @@ static auto locked_controls_schemes(lua_State* L) -> int {
return 1;
}
+static auto haptics_modes(lua_State* L) -> int {
+ lua_newtable(L);
+
+ lua_pushliteral(L, "Disabled");
+ lua_rawseti(L, -2,
+ static_cast<int>(drivers::NvsStorage::HapticsModes::kDisabled));
+
+ lua_pushliteral(L, "Minimal");
+ lua_rawseti(
+ L, -2,
+ static_cast<int>(drivers::NvsStorage::HapticsModes::kMinimal));
+
+ lua_pushliteral(L, "Strong");
+ lua_rawseti(
+ L, -2, static_cast<int>(drivers::NvsStorage::HapticsModes::kStrong));
+
+ return 1;
+}
+
static const struct luaL_Reg kControlsFuncs[] = {{"schemes", controls_schemes},
{"locked_schemes", locked_controls_schemes},
+ {"haptics_modes", haptics_modes},
{NULL, NULL}};
static auto lua_controls(lua_State* state) -> int {
diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp
index 1823f780..b974da53 100644
--- a/src/tangara/ui/ui_fsm.cpp
+++ b/src/tangara/ui/ui_fsm.cpp
@@ -668,6 +668,7 @@ void Lua::entry() {
{
{"scheme", &sInput->mode()},
{"locked_scheme", &sInput->lockedMode()},
+ {"haptics_mode", &sInput->hapticsMode()},
{"lock_switch", &sLockSwitch},
{"hooks", [&](lua_State* L) { return sInput->pushHooks(L); }},
});