summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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); }},
});