summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/include/drivers/nvs.hpp27
-rw-r--r--src/drivers/nvs.cpp77
-rw-r--r--src/tangara/input/device_factory.cpp60
-rw-r--r--src/tangara/input/device_factory.hpp9
-rw-r--r--src/tangara/input/input_device.hpp2
-rw-r--r--src/tangara/input/input_hook_actions.cpp21
-rw-r--r--src/tangara/input/input_hook_actions.hpp8
-rw-r--r--src/tangara/input/input_media_buttons.cpp62
-rw-r--r--src/tangara/input/input_media_buttons.hpp43
-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.cpp2
-rw-r--r--src/tangara/input/input_touch_wheel.hpp2
-rw-r--r--src/tangara/input/input_volume_buttons.cpp10
-rw-r--r--src/tangara/input/input_volume_buttons.hpp5
-rw-r--r--src/tangara/input/lvgl_input_driver.cpp114
-rw-r--r--src/tangara/input/lvgl_input_driver.hpp14
-rw-r--r--src/tangara/lua/lua_controls.cpp50
-rw-r--r--src/tangara/ui/ui_fsm.cpp3
21 files changed, 388 insertions, 129 deletions
diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp
index 7ef1fbf7..b490ac3d 100644
--- a/src/drivers/include/drivers/nvs.hpp
+++ b/src/drivers/include/drivers/nvs.hpp
@@ -143,23 +143,27 @@ class NvsStorage {
auto AmpLeftBias() -> int_fast8_t;
auto AmpLeftBias(int_fast8_t) -> void;
- enum class InputModes : uint8_t {
- kButtonsOnly = 0,
- kButtonsWithWheel = 1,
- kDirectionalWheel = 2,
- kRotatingWheel = 3,
+ enum class WheelInputModes : uint8_t {
+ kDisabled = 0,
+ kDirectionalWheel = 1,
+ kRotatingWheel = 2,
};
- auto PrimaryInput() -> InputModes;
- auto PrimaryInput(InputModes) -> void;
+ auto WheelInput() -> WheelInputModes;
+ auto WheelInput(WheelInputModes) -> void;
- enum class LockedInputModes : uint8_t {
+ enum class ButtonInputModes : uint8_t {
kDisabled = 0,
kVolumeOnly = 1,
+ kMediaControls = 2,
+ kNavigation = 3,
};
- auto LockedInput() -> LockedInputModes;
- auto LockedInput(LockedInputModes) -> void;
+ auto ButtonInput() -> ButtonInputModes;
+ auto ButtonInput(ButtonInputModes) -> void;
+
+ auto LockedInput() -> ButtonInputModes;
+ auto LockedInput(ButtonInputModes) -> void;
auto QueueRepeatMode() -> uint8_t;
auto QueueRepeatMode(uint8_t) -> void;
@@ -191,7 +195,8 @@ class NvsStorage {
Setting<uint16_t> amp_max_vol_;
Setting<uint16_t> amp_cur_vol_;
Setting<int8_t> amp_left_bias_;
- Setting<uint8_t> input_mode_;
+ Setting<uint8_t> wheel_input_mode_;
+ Setting<uint8_t> button_input_mode_;
Setting<uint8_t> locked_input_mode_;
Setting<uint8_t> output_mode_;
Setting<uint8_t> haptics_mode_;
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index 374c71d6..64ed9c1a 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -34,7 +34,8 @@ static constexpr char kKeyInterfaceTheme[] = "ui_theme";
static constexpr char kKeyAmpMaxVolume[] = "hp_vol_max";
static constexpr char kKeyAmpCurrentVolume[] = "hp_vol";
static constexpr char kKeyAmpLeftBias[] = "hp_bias";
-static constexpr char kKeyPrimaryInput[] = "in_pri";
+static constexpr char kKeyWheelInput[] = "in_wheel";
+static constexpr char kKeyButtonInput[] = "in_btn";
static constexpr char kKeyLockedInput[] = "in_locked";
static constexpr char kKeyHaptics[] = "haptic_mode";
static constexpr char kKeyScrollSensitivity[] = "scroll";
@@ -277,7 +278,8 @@ NvsStorage::NvsStorage(nvs_handle_t handle)
amp_max_vol_(kKeyAmpMaxVolume),
amp_cur_vol_(kKeyAmpCurrentVolume),
amp_left_bias_(kKeyAmpLeftBias),
- input_mode_(kKeyPrimaryInput),
+ wheel_input_mode_(kKeyWheelInput),
+ button_input_mode_(kKeyButtonInput),
locked_input_mode_(kKeyLockedInput),
output_mode_(kKeyOutput),
haptics_mode_(kKeyHaptics),
@@ -309,7 +311,8 @@ auto NvsStorage::Read() -> void {
amp_max_vol_.read(handle_);
amp_cur_vol_.read(handle_);
amp_left_bias_.read(handle_);
- input_mode_.read(handle_);
+ wheel_input_mode_.read(handle_);
+ button_input_mode_.read(handle_);
locked_input_mode_.read(handle_);
output_mode_.read(handle_);
haptics_mode_.read(handle_);
@@ -336,7 +339,8 @@ auto NvsStorage::Write() -> bool {
amp_max_vol_.write(handle_);
amp_cur_vol_.write(handle_);
amp_left_bias_.write(handle_);
- input_mode_.write(handle_);
+ wheel_input_mode_.write(handle_);
+ button_input_mode_.write(handle_);
locked_input_mode_.write(handle_);
output_mode_.write(handle_);
haptics_mode_.write(handle_);
@@ -615,40 +619,63 @@ auto NvsStorage::AmpLeftBias(int_fast8_t val) -> void {
amp_left_bias_.set(val);
}
-auto NvsStorage::PrimaryInput() -> InputModes {
+auto NvsStorage::WheelInput() -> WheelInputModes {
std::lock_guard<std::mutex> lock{mutex_};
- switch (input_mode_.get().value_or(3)) {
- case static_cast<uint8_t>(InputModes::kButtonsOnly):
- return InputModes::kButtonsOnly;
- case static_cast<uint8_t>(InputModes::kButtonsWithWheel):
- return InputModes::kButtonsWithWheel;
- case static_cast<uint8_t>(InputModes::kDirectionalWheel):
- return InputModes::kDirectionalWheel;
- case static_cast<uint8_t>(InputModes::kRotatingWheel):
- return InputModes::kRotatingWheel;
+ switch (wheel_input_mode_.get().value_or(3)) {
+ case static_cast<uint8_t>(WheelInputModes::kDisabled):
+ return WheelInputModes::kDisabled;
+ case static_cast<uint8_t>(WheelInputModes::kDirectionalWheel):
+ return WheelInputModes::kDirectionalWheel;
+ case static_cast<uint8_t>(WheelInputModes::kRotatingWheel):
+ return WheelInputModes::kRotatingWheel;
default:
- return InputModes::kRotatingWheel;
+ return WheelInputModes::kRotatingWheel;
}
}
-auto NvsStorage::PrimaryInput(InputModes mode) -> void {
+auto NvsStorage::WheelInput(WheelInputModes mode) -> void {
std::lock_guard<std::mutex> lock{mutex_};
- input_mode_.set(static_cast<uint8_t>(mode));
+ wheel_input_mode_.set(static_cast<uint8_t>(mode));
}
-auto NvsStorage::LockedInput() -> LockedInputModes {
+auto NvsStorage::ButtonInput() -> ButtonInputModes {
std::lock_guard<std::mutex> lock{mutex_};
- switch (locked_input_mode_.get().value_or(static_cast<uint8_t>(LockedInputModes::kDisabled))) {
- case static_cast<uint8_t>(LockedInputModes::kDisabled):
- return LockedInputModes::kDisabled;
- case static_cast<uint8_t>(LockedInputModes::kVolumeOnly):
- return LockedInputModes::kVolumeOnly;
+ switch (button_input_mode_.get().value_or(static_cast<uint8_t>(ButtonInputModes::kVolumeOnly))) {
+ case static_cast<uint8_t>(ButtonInputModes::kDisabled):
+ return ButtonInputModes::kDisabled;
+ case static_cast<uint8_t>(ButtonInputModes::kVolumeOnly):
+ return ButtonInputModes::kVolumeOnly;
+ case static_cast<uint8_t>(ButtonInputModes::kMediaControls):
+ return ButtonInputModes::kMediaControls;
+ case static_cast<uint8_t>(ButtonInputModes::kNavigation):
+ return ButtonInputModes::kNavigation;
default:
- return LockedInputModes::kDisabled;
+ return ButtonInputModes::kVolumeOnly;
}
}
-auto NvsStorage::LockedInput(LockedInputModes mode) -> void {
+auto NvsStorage::ButtonInput(ButtonInputModes mode) -> void {
+ std::lock_guard<std::mutex> lock{mutex_};
+ button_input_mode_.set(static_cast<uint8_t>(mode));
+}
+
+auto NvsStorage::LockedInput() -> ButtonInputModes {
+ std::lock_guard<std::mutex> lock{mutex_};
+ switch (locked_input_mode_.get().value_or(static_cast<uint8_t>(ButtonInputModes::kDisabled))) {
+ case static_cast<uint8_t>(ButtonInputModes::kDisabled):
+ return ButtonInputModes::kDisabled;
+ case static_cast<uint8_t>(ButtonInputModes::kVolumeOnly):
+ return ButtonInputModes::kVolumeOnly;
+ case static_cast<uint8_t>(ButtonInputModes::kMediaControls):
+ return ButtonInputModes::kMediaControls;
+ case static_cast<uint8_t>(ButtonInputModes::kNavigation):
+ return ButtonInputModes::kNavigation;
+ default:
+ return ButtonInputModes::kDisabled;
+ }
+}
+
+auto NvsStorage::LockedInput(ButtonInputModes mode) -> void {
std::lock_guard<std::mutex> lock{mutex_};
locked_input_mode_.set(static_cast<uint8_t>(mode));
}
diff --git a/src/tangara/input/device_factory.cpp b/src/tangara/input/device_factory.cpp
index fe2e2485..ff597556 100644
--- a/src/tangara/input/device_factory.cpp
+++ b/src/tangara/input/device_factory.cpp
@@ -16,6 +16,7 @@
#include "input/input_touch_dpad.hpp"
#include "input/input_touch_wheel.hpp"
#include "input/input_volume_buttons.hpp"
+#include "input/input_media_buttons.hpp"
namespace input {
@@ -26,30 +27,73 @@ DeviceFactory::DeviceFactory(
wheel_ =
std::make_shared<TouchWheel>(services->nvs(), **services->touchwheel());
}
+ reset_ = std::make_shared<HardReset>(services_->gpios());
}
-auto DeviceFactory::createInputs(drivers::NvsStorage::InputModes mode)
+auto DeviceFactory::createLockedInputs()
-> std::vector<std::shared_ptr<IInputDevice>> {
+ auto locked_mode = services_->nvs().LockedInput();
std::vector<std::shared_ptr<IInputDevice>> ret;
- switch (mode) {
- case drivers::NvsStorage::InputModes::kButtonsOnly:
- ret.push_back(std::make_shared<NavButtons>(services_->gpios()));
+ switch (locked_mode) {
+ case drivers::NvsStorage::ButtonInputModes::kDisabled:
+ break;
+ case drivers::NvsStorage::ButtonInputModes::kMediaControls:
+ ret.push_back(std::make_shared<MediaButtons>(services_->gpios(), services_->track_queue()));
+ break;
+ case drivers::NvsStorage::ButtonInputModes::kNavigation:
+ // I don't think we want navigation to work when locked?
+ // ret.push_back(std::make_shared<NavButtons>(services_->gpios()));
break;
- case drivers::NvsStorage::InputModes::kDirectionalWheel:
+ case drivers::NvsStorage::ButtonInputModes::kVolumeOnly:
ret.push_back(std::make_shared<VolumeButtons>(services_->gpios()));
+ break;
+ }
+ ret.push_back(reset_);
+ return ret;
+}
+
+auto DeviceFactory::createInputs()
+ -> std::vector<std::shared_ptr<IInputDevice>> {
+ std::vector<std::shared_ptr<IInputDevice>> ret;
+ auto wheel_mode = services_->nvs().WheelInput();
+ auto buttons_mode = services_->nvs().ButtonInput();
+ // Make sure we always have a navigational input
+ if (wheel_mode == drivers::NvsStorage::WheelInputModes::kDisabled) {
+ if (buttons_mode != drivers::NvsStorage::ButtonInputModes::kNavigation) {
+ wheel_mode = drivers::NvsStorage::WheelInputModes::kRotatingWheel;
+ services_->nvs().WheelInput(wheel_mode);
+ }
+ }
+ switch (wheel_mode) {
+ case drivers::NvsStorage::WheelInputModes::kDisabled:
+ break;
+ case drivers::NvsStorage::WheelInputModes::kDirectionalWheel:
if (services_->touchwheel()) {
ret.push_back(std::make_shared<TouchDPad>(**services_->touchwheel()));
}
break;
- case drivers::NvsStorage::InputModes::kRotatingWheel:
+ case drivers::NvsStorage::WheelInputModes::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;
}
- ret.push_back(std::make_shared<HardReset>(services_->gpios()));
+ switch (buttons_mode) {
+ case drivers::NvsStorage::ButtonInputModes::kDisabled:
+ break;
+ case drivers::NvsStorage::ButtonInputModes::kMediaControls:
+ ret.push_back(std::make_shared<MediaButtons>(services_->gpios(), services_->track_queue()));
+ break;
+ case drivers::NvsStorage::ButtonInputModes::kNavigation:
+ ret.push_back(std::make_shared<NavButtons>(services_->gpios()));
+ break;
+ case drivers::NvsStorage::ButtonInputModes::kVolumeOnly:
+ default:
+ ret.push_back(std::make_shared<VolumeButtons>(services_->gpios()));
+ break;
+ }
+ ret.push_back(reset_);
return ret;
}
diff --git a/src/tangara/input/device_factory.hpp b/src/tangara/input/device_factory.hpp
index 5044d025..1f95bbef 100644
--- a/src/tangara/input/device_factory.hpp
+++ b/src/tangara/input/device_factory.hpp
@@ -12,6 +12,7 @@
#include "input/feedback_device.hpp"
#include "input/input_device.hpp"
#include "input/input_touch_wheel.hpp"
+#include "input/input_hard_reset.hpp"
#include "drivers/nvs.hpp"
#include "system_fsm/service_locator.hpp"
@@ -21,7 +22,9 @@ class DeviceFactory {
public:
DeviceFactory(std::shared_ptr<system_fsm::ServiceLocator>);
- auto createInputs(drivers::NvsStorage::InputModes mode)
+ auto createInputs()
+ -> std::vector<std::shared_ptr<IInputDevice>>;
+ auto createLockedInputs()
-> std::vector<std::shared_ptr<IInputDevice>>;
auto createFeedbacks() -> std::vector<std::shared_ptr<IFeedbackDevice>>;
@@ -34,6 +37,10 @@ class DeviceFactory {
// 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_;
+
+ // Another special case, the hard reset input should persist between
+ // lock modes, and always be added to the created inputs
+ std::shared_ptr<HardReset> reset_;
};
} // namespace input
diff --git a/src/tangara/input/input_device.hpp b/src/tangara/input/input_device.hpp
index 7b8d993d..183781bc 100644
--- a/src/tangara/input/input_device.hpp
+++ b/src/tangara/input/input_device.hpp
@@ -36,7 +36,7 @@ class IInputDevice {
}
/* Called by the LVGL driver when controls are being locked. */
- virtual auto onLock(drivers::NvsStorage::LockedInputModes) -> void {}
+ virtual auto onLock() -> void {}
/* Called by the LVGL driver when controls are being unlocked. */
virtual auto onUnlock() -> void {}
};
diff --git a/src/tangara/input/input_hook_actions.cpp b/src/tangara/input/input_hook_actions.cpp
index fb6a677c..001d3fb0 100644
--- a/src/tangara/input/input_hook_actions.cpp
+++ b/src/tangara/input/input_hook_actions.cpp
@@ -62,11 +62,22 @@ auto volumeDown() -> HookCallback {
}};
}
-auto allActions() -> std::vector<HookCallback> {
- return {
- select(), scrollUp(), scrollDown(), scrollToTop(),
- scrollToBottom(), goBack(), volumeUp(), volumeDown(),
- };
+auto nextTrack(audio::TrackQueue& queue) -> HookCallback {
+ return HookCallback{.name = "next_track", .fn = [&](lv_indev_data_t* d) {
+ queue.next();
+ }};
+}
+
+auto prevTrack(audio::TrackQueue& queue) -> HookCallback {
+ return HookCallback{.name = "prev_track", .fn = [&](lv_indev_data_t* d) {
+ queue.previous();
+ }};
+}
+
+auto togglePlayPause() -> HookCallback {
+ return HookCallback{.name = "toggle_play_pause", .fn = [&](lv_indev_data_t* d) {
+ events::Audio().Dispatch(audio::TogglePlayPause{});
+ }};
}
} // namespace actions
diff --git a/src/tangara/input/input_hook_actions.hpp b/src/tangara/input/input_hook_actions.hpp
index bca82af6..2db0b6e7 100644
--- a/src/tangara/input/input_hook_actions.hpp
+++ b/src/tangara/input/input_hook_actions.hpp
@@ -7,6 +7,7 @@
#pragma once
#include "input/input_hook.hpp"
+#include "audio/track_queue.hpp"
namespace input {
namespace actions {
@@ -21,10 +22,13 @@ auto scrollToBottom() -> HookCallback;
auto goBack() -> HookCallback;
+auto togglePlayPause() -> HookCallback;
+
+auto nextTrack(audio::TrackQueue& queue) -> HookCallback;
+auto prevTrack(audio::TrackQueue& queue) -> HookCallback;
+
auto volumeUp() -> HookCallback;
auto volumeDown() -> HookCallback;
-auto allActions() -> std::vector<HookCallback>;
-
} // namespace actions
} // namespace input
diff --git a/src/tangara/input/input_media_buttons.cpp b/src/tangara/input/input_media_buttons.cpp
new file mode 100644
index 00000000..94d7dd12
--- /dev/null
+++ b/src/tangara/input/input_media_buttons.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2025 ailurux <ailuruxx@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "input/input_media_buttons.hpp"
+#include "drivers/gpios.hpp"
+#include "events/event_queue.hpp"
+#include "input/input_hook_actions.hpp"
+
+namespace input {
+
+MediaButtons::MediaButtons(drivers::IGpios& gpios, audio::TrackQueue& queue)
+ : gpios_(gpios),
+ up_("upper", actions::nextTrack(queue), {}, {}, actions::volumeUp()),
+ down_("lower", actions::prevTrack(queue), {}, {}, actions::volumeDown()),
+ locked_(),
+ both_buttons_pressed_(false) {}
+
+auto MediaButtons::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);
+
+ if ((up && down)) {
+ up_.cancel();
+ down_.cancel();
+ both_buttons_pressed_ = true;
+ } else if (!up && !down) {
+ if (both_buttons_pressed_) {
+ std::invoke(actions::togglePlayPause().fn, data);
+ both_buttons_pressed_ = false;
+ return;
+ }
+ }
+
+ if (both_buttons_pressed_) {
+ return;
+ }
+
+ up_.update(up, data);
+ down_.update(down, data);
+}
+
+auto MediaButtons::name() -> std::string {
+ return "buttons";
+}
+
+auto MediaButtons::triggers()
+ -> std::vector<std::reference_wrapper<TriggerHooks>> {
+ return {up_, down_};
+}
+
+auto MediaButtons::onLock() -> void {
+ locked_ = true;
+}
+
+auto MediaButtons::onUnlock() -> void {
+ locked_ = false;
+}
+
+} // namespace input
diff --git a/src/tangara/input/input_media_buttons.hpp b/src/tangara/input/input_media_buttons.hpp
new file mode 100644
index 00000000..02ee90d3
--- /dev/null
+++ b/src/tangara/input/input_media_buttons.hpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2025 ailurux <ailuruxx@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "indev/lv_indev.h"
+
+#include "drivers/gpios.hpp"
+#include "drivers/haptics.hpp"
+#include "drivers/touchwheel.hpp"
+#include "input/input_device.hpp"
+#include "input/input_hook.hpp"
+
+namespace input {
+
+class MediaButtons : public IInputDevice {
+ public:
+ MediaButtons(drivers::IGpios&, audio::TrackQueue& queue);
+
+ 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;
+
+ auto onLock() -> void override;
+ auto onUnlock() -> void override;
+
+ private:
+ drivers::IGpios& gpios_;
+
+ TriggerHooks up_;
+ TriggerHooks down_;
+
+ bool locked_;
+ bool both_buttons_pressed_;
+};
+
+} // namespace input
diff --git a/src/tangara/input/input_nav_buttons.cpp b/src/tangara/input/input_nav_buttons.cpp
index ede6b714..b1279b44 100644
--- a/src/tangara/input/input_nav_buttons.cpp
+++ b/src/tangara/input/input_nav_buttons.cpp
@@ -42,7 +42,7 @@ auto NavButtons::triggers()
return {up_, down_};
}
-auto NavButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void {
+auto NavButtons::onLock() -> void {
locked_ = true;
}
diff --git a/src/tangara/input/input_nav_buttons.hpp b/src/tangara/input/input_nav_buttons.hpp
index c28cce91..03b337d3 100644
--- a/src/tangara/input/input_nav_buttons.hpp
+++ b/src/tangara/input/input_nav_buttons.hpp
@@ -28,7 +28,7 @@ class NavButtons : public IInputDevice {
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
- auto onLock(drivers::NvsStorage::LockedInputModes) -> void override;
+ auto onLock() -> void override;
auto onUnlock() -> void override;
private:
diff --git a/src/tangara/input/input_touch_dpad.cpp b/src/tangara/input/input_touch_dpad.cpp
index c866f37c..b6c61237 100644
--- a/src/tangara/input/input_touch_dpad.cpp
+++ b/src/tangara/input/input_touch_dpad.cpp
@@ -65,7 +65,7 @@ auto TouchDPad::triggers()
return {centre_, up_, right_, down_, left_};
}
-auto TouchDPad::onLock(drivers::NvsStorage::LockedInputModes mode) -> void {
+auto TouchDPad::onLock() -> void {
wheel_.LowPowerMode(true);
locked_ = true;
}
diff --git a/src/tangara/input/input_touch_dpad.hpp b/src/tangara/input/input_touch_dpad.hpp
index 82de26bf..bf772d73 100644
--- a/src/tangara/input/input_touch_dpad.hpp
+++ b/src/tangara/input/input_touch_dpad.hpp
@@ -27,7 +27,7 @@ class TouchDPad : public IInputDevice {
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
- auto onLock(drivers::NvsStorage::LockedInputModes) -> void override;
+ auto onLock() -> void override;
auto onUnlock() -> void override;
private:
diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp
index 29153396..ae192e31 100644
--- a/src/tangara/input/input_touch_wheel.cpp
+++ b/src/tangara/input/input_touch_wheel.cpp
@@ -130,7 +130,7 @@ auto TouchWheel::triggers()
return {centre_, up_, right_, down_, left_};
}
-auto TouchWheel::onLock(drivers::NvsStorage::LockedInputModes mode) -> void {
+auto TouchWheel::onLock() -> void {
wheel_.LowPowerMode(true);
locked_ = true;
}
diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp
index b2583e85..3f2ed49e 100644
--- a/src/tangara/input/input_touch_wheel.hpp
+++ b/src/tangara/input/input_touch_wheel.hpp
@@ -30,7 +30,7 @@ class TouchWheel : public IInputDevice {
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
- auto onLock(drivers::NvsStorage::LockedInputModes) -> void override;
+ auto onLock() -> void override;
auto onUnlock() -> void override;
auto sensitivity() -> lua::Property&;
diff --git a/src/tangara/input/input_volume_buttons.cpp b/src/tangara/input/input_volume_buttons.cpp
index ffeea18f..d6c50e2f 100644
--- a/src/tangara/input/input_volume_buttons.cpp
+++ b/src/tangara/input/input_volume_buttons.cpp
@@ -21,9 +21,7 @@ auto VolumeButtons::read(lv_indev_data_t* data, std::vector<InputEvent>& events)
bool up = !gpios_.Get(drivers::IGpios::Pin::kKeyUp);
bool down = !gpios_.Get(drivers::IGpios::Pin::kKeyDown);
- bool input_disabled = locked_.has_value() && (locked_ != drivers::NvsStorage::LockedInputModes::kVolumeOnly);
-
- if ((up && down) || input_disabled) {
+ if ((up && down)) {
up = false;
down = false;
}
@@ -41,12 +39,12 @@ auto VolumeButtons::triggers()
return {up_, down_};
}
-auto VolumeButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void {
- locked_ = mode;
+auto VolumeButtons::onLock() -> void {
+ locked_ = true;
}
auto VolumeButtons::onUnlock() -> void {
- locked_ = {};
+ locked_ = false;
}
} // namespace input
diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp
index 17f60d7e..8559d496 100644
--- a/src/tangara/input/input_volume_buttons.hpp
+++ b/src/tangara/input/input_volume_buttons.hpp
@@ -27,7 +27,7 @@ class VolumeButtons : public IInputDevice {
auto name() -> std::string override;
auto triggers() -> std::vector<std::reference_wrapper<TriggerHooks>> override;
- auto onLock(drivers::NvsStorage::LockedInputModes) -> void override;
+ auto onLock() -> void override;
auto onUnlock() -> void override;
private:
@@ -36,8 +36,7 @@ class VolumeButtons : public IInputDevice {
TriggerHooks up_;
TriggerHooks down_;
- // When locked, this contains the active mode
- std::optional<drivers::NvsStorage::LockedInputModes> locked_;
+ bool locked_;
};
} // namespace input
diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp
index 03d5cbb7..b4bab365 100644
--- a/src/tangara/input/lvgl_input_driver.cpp
+++ b/src/tangara/input/lvgl_input_driver.cpp
@@ -55,63 +55,94 @@ static void focus_cb(lv_group_t* group) {
namespace {
-auto intToMode(int raw) -> std::optional<drivers::NvsStorage::InputModes> {
+auto intToWheelMode(int raw)
+ -> std::optional<drivers::NvsStorage::WheelInputModes> {
switch (raw) {
case 0:
- return drivers::NvsStorage::InputModes::kButtonsOnly;
+ return drivers::NvsStorage::WheelInputModes::kDisabled;
case 1:
- return drivers::NvsStorage::InputModes::kButtonsWithWheel;
+ return drivers::NvsStorage::WheelInputModes::kDirectionalWheel;
case 2:
- return drivers::NvsStorage::InputModes::kDirectionalWheel;
- case 3:
- return drivers::NvsStorage::InputModes::kRotatingWheel;
+ return drivers::NvsStorage::WheelInputModes::kRotatingWheel;
default:
return {};
}
}
-auto intToLockedMode(int raw) -> std::optional<drivers::NvsStorage::LockedInputModes> {
+auto intToButtonMode(int raw)
+ -> std::optional<drivers::NvsStorage::ButtonInputModes> {
switch (raw) {
case 0:
- return drivers::NvsStorage::LockedInputModes::kDisabled;
+ return drivers::NvsStorage::ButtonInputModes::kDisabled;
case 1:
- return drivers::NvsStorage::LockedInputModes::kVolumeOnly;
+ return drivers::NvsStorage::ButtonInputModes::kVolumeOnly;
+ case 2:
+ return drivers::NvsStorage::ButtonInputModes::kMediaControls;
+ case 3:
+ return drivers::NvsStorage::ButtonInputModes::kNavigation;
default:
return {};
}
}
-} // namespace {}
+} // namespace
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;
- }),
+ wheel_mode_(
+ static_cast<int>(nvs.WheelInput()),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ auto mode = intToWheelMode(std::get<int>(val));
+ if (!mode) {
+ return false;
+ }
+ // Only allow disabling wheel if side buttons are
+ // used for navigation
+ if (*mode == drivers::NvsStorage::WheelInputModes::kDisabled &&
+ nvs.ButtonInput() !=
+ drivers::NvsStorage::ButtonInputModes::kNavigation) {
+ return false;
+ }
+ nvs.WheelInput(*mode);
+ inputs_ = factory.createInputs();
+ return true;
+ }),
+ button_mode_(
+ static_cast<int>(nvs.ButtonInput()),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ auto mode = intToButtonMode(std::get<int>(val));
+ if (!mode) {
+ return false;
+ }
+ // Ensure we don't remove the only navigation control
+ if (*mode != drivers::NvsStorage::ButtonInputModes::kNavigation &&
+ nvs.WheelInput() == drivers::NvsStorage::WheelInputModes::kDisabled) {
+ return false;
+ }
+ nvs.ButtonInput(*mode);
+ inputs_ = factory.createInputs();
+ return true;
+ }),
locked_mode_(static_cast<int>(nvs.LockedInput()),
- [&](const lua::LuaValue& val) {
- if (!std::holds_alternative<int>(val)) {
- return false;
- }
- auto mode = intToLockedMode(std::get<int>(val));
- if (!mode) {
- return false;
- }
- nvs.LockedInput(*mode);
- return true;
- }),
+ [&](const lua::LuaValue& val) {
+ if (!std::holds_alternative<int>(val)) {
+ return false;
+ }
+ auto mode = intToButtonMode(std::get<int>(val));
+ if (!mode) {
+ return false;
+ }
+ nvs.LockedInput(*mode);
+ return true;
+ }),
haptics_mode_(static_cast<int>(nvs.HapticsMode()),
[&](const lua::LuaValue& val) {
if (!std::holds_alternative<int>(val)) {
@@ -121,7 +152,7 @@ LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs,
nvs.HapticsMode(mode);
return true;
}),
- inputs_(factory.createInputs(nvs.PrimaryInput())),
+ inputs_(factory.createInputs()),
feedbacks_(factory.createFeedbacks()),
is_locked_(false) {
device_ = lv_indev_create();
@@ -172,14 +203,11 @@ auto LvglInputDriver::feedback(uint8_t event) -> void {
auto LvglInputDriver::lock(bool l) -> void {
is_locked_ = l;
- auto locked_input_mode = nvs_.LockedInput();
-
- for (auto&& device : inputs_) {
- if (l) {
- device->onLock(locked_input_mode);
- } else {
- device->onUnlock();
- }
+ // Todo:: Call onLock/onUnlock on inputs_?
+ if (l) {
+ inputs_ = factory_.createLockedInputs();
+ } else {
+ inputs_ = factory_.createInputs();
}
}
diff --git a/src/tangara/input/lvgl_input_driver.hpp b/src/tangara/input/lvgl_input_driver.hpp
index 629a0a78..ecb3a36d 100644
--- a/src/tangara/input/lvgl_input_driver.hpp
+++ b/src/tangara/input/lvgl_input_driver.hpp
@@ -35,7 +35,8 @@ class LvglInputDriver {
public:
LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory&);
- auto mode() -> lua::Property& { return mode_; }
+ auto wheelMode() -> lua::Property& { return wheel_mode_; }
+ auto buttonMode() -> lua::Property& { return button_mode_; }
auto lockedMode() -> lua::Property& { return locked_mode_; }
auto hapticsMode() -> lua::Property& { return haptics_mode_; }
@@ -50,7 +51,8 @@ class LvglInputDriver {
drivers::NvsStorage& nvs_;
DeviceFactory& factory_;
- lua::Property mode_;
+ lua::Property wheel_mode_;
+ lua::Property button_mode_;
lua::Property locked_mode_;
lua::Property haptics_mode_;
lv_indev_t* device_;
@@ -73,8 +75,6 @@ class LvglInputDriver {
std::tie(r.device_name, r.trigger_name, r.hook_name);
}
};
-
- /* Userdata object for tracking the Lua mirror of a TriggerHooks object. */
class LuaTrigger {
public:
LuaTrigger(LvglInputDriver&, IInputDevice&, TriggerHooks&);
@@ -96,13 +96,15 @@ class LvglInputDriver {
std::string trigger_;
std::map<std::string, std::string> hooks_;
};
-
- /* A hook override implemented as a lua callback */
struct LuaOverride {
lua_State* L;
int ref;
};
+ /* Userdata object for tracking the Lua mirror of a TriggerHooks object. */
+
+ /* A hook override implemented as a lua callback */
+
std::map<OverrideSelector, LuaOverride> overrides_;
auto setOverride(lua_State* L, const OverrideSelector&) -> void;
diff --git a/src/tangara/lua/lua_controls.cpp b/src/tangara/lua/lua_controls.cpp
index bc2588ac..69053f43 100644
--- a/src/tangara/lua/lua_controls.cpp
+++ b/src/tangara/lua/lua_controls.cpp
@@ -23,37 +23,64 @@ namespace lua {
[[maybe_unused]] static constexpr char kTag[] = "lua_controls";
-static auto controls_schemes(lua_State* L) -> int {
+static auto wheel_schemes(lua_State* L) -> int {
lua_newtable(L);
- lua_pushliteral(L, "Buttons Only");
+ lua_pushliteral(L, "Disabled");
lua_rawseti(L, -2,
- static_cast<int>(drivers::NvsStorage::InputModes::kButtonsOnly));
+ static_cast<int>(drivers::NvsStorage::WheelInputModes::kDisabled));
lua_pushliteral(L, "D-Pad");
+ lua_rawseti(L, -2,
+ static_cast<int>(drivers::NvsStorage::WheelInputModes::kDirectionalWheel));
+
+ lua_pushliteral(L, "Touchwheel");
+ lua_rawseti(
+ L, -2, static_cast<int>(drivers::NvsStorage::WheelInputModes::kRotatingWheel));
+
+ return 1;
+}
+
+static auto button_schemes(lua_State* L) -> int {
+ lua_newtable(L);
+
+ lua_pushliteral(L, "Disabled");
lua_rawseti(
L, -2,
- static_cast<int>(drivers::NvsStorage::InputModes::kDirectionalWheel));
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kDisabled));
- lua_pushliteral(L, "Touchwheel");
+ lua_pushliteral(L, "Volume Only");
+ lua_rawseti(
+ L, -2,
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kVolumeOnly));
+ lua_pushliteral(L, "Media Controls");
lua_rawseti(
- L, -2, static_cast<int>(drivers::NvsStorage::InputModes::kRotatingWheel));
+ L, -2,
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kMediaControls));
+ lua_pushliteral(L, "Navigation");
+ lua_rawseti(
+ L, -2,
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kNavigation));
return 1;
}
-static auto locked_controls_schemes(lua_State* L) -> int {
+static auto locked_button_schemes(lua_State* L) -> int {
lua_newtable(L);
lua_pushliteral(L, "Disabled");
lua_rawseti(
L, -2,
- static_cast<int>(drivers::NvsStorage::LockedInputModes::kDisabled));
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kDisabled));
lua_pushliteral(L, "Volume Only");
lua_rawseti(
L, -2,
- static_cast<int>(drivers::NvsStorage::LockedInputModes::kVolumeOnly));
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kVolumeOnly));
+ lua_pushliteral(L, "Media Controls");
+ lua_rawseti(
+ L, -2,
+ static_cast<int>(drivers::NvsStorage::ButtonInputModes::kMediaControls));
return 1;
}
@@ -77,8 +104,9 @@ static auto haptics_modes(lua_State* L) -> int {
return 1;
}
-static const struct luaL_Reg kControlsFuncs[] = {{"schemes", controls_schemes},
- {"locked_schemes", locked_controls_schemes},
+static const struct luaL_Reg kControlsFuncs[] = {{"wheel_schemes", wheel_schemes},
+ {"button_schemes", button_schemes},
+ {"locked_schemes", locked_button_schemes},
{"haptics_modes", haptics_modes},
{NULL, NULL}};
diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp
index 020917e2..aaf35d13 100644
--- a/src/tangara/ui/ui_fsm.cpp
+++ b/src/tangara/ui/ui_fsm.cpp
@@ -680,7 +680,8 @@ void Lua::entry() {
registry.AddPropertyModule(
"controls",
{
- {"scheme", &sInput->mode()},
+ {"wheel_scheme", &sInput->wheelMode()},
+ {"button_scheme", &sInput->buttonMode()},
{"locked_scheme", &sInput->lockedMode()},
{"haptics_mode", &sInput->hapticsMode()},
{"lock_switch", &sLockSwitch},