From 6c323f0fd075beb406df04d444fc4029b733ceb4 Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 00:16:04 -0500 Subject: Don't detect center button touch until 250ms after wheel touch --- src/tangara/input/input_touch_wheel.cpp | 13 ++++++++++++- src/tangara/input/input_touch_wheel.hpp | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp index 19ac5211..6621a77e 100644 --- a/src/tangara/input/input_touch_wheel.cpp +++ b/src/tangara/input/input_touch_wheel.cpp @@ -21,6 +21,8 @@ #include "lua/property.hpp" #include "ui/ui_events.hpp" +#include "esp_timer.h" + namespace input { TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel) @@ -77,7 +79,16 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void { data->enc_diff = 0; } - centre_.update(wheel_data.is_button_touched && !wheel_data.is_wheel_touched, + // Prevent accidental center button touches while scrolling + if (wheel_data.is_wheel_touched) { + last_wheel_touch_time_ = esp_timer_get_time(); + } + + 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 && + !wheel_data.is_wheel_touched, data); // If the user is touching the wheel but not scrolling, then they may be diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp index 982f89f4..00da99f1 100644 --- a/src/tangara/input/input_touch_wheel.hpp +++ b/src/tangara/input/input_touch_wheel.hpp @@ -36,6 +36,8 @@ class TouchWheel : public IInputDevice { auto sensitivity() -> lua::Property&; private: + const int64_t SCROLL_TIMEOUT_US = 250000; // 250ms + auto calculateTicks(const drivers::TouchWheelData& data) -> int8_t; auto calculateThreshold(uint8_t sensitivity) -> uint8_t; @@ -55,6 +57,7 @@ class TouchWheel : public IInputDevice { uint8_t threshold_; bool is_first_read_; uint8_t last_angle_; + int64_t last_wheel_touch_time_; }; } // namespace input -- cgit v1.2.3 From e8eaf3df10a896cb28e91cfc416b19303926a00a Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sat, 1 Feb 2025 15:59:08 -0800 Subject: Add a new setting for input controls when locked This is just the plumbing of the new setting. The input methods will come in subsequent patches. --- src/drivers/include/drivers/nvs.hpp | 8 ++++++++ src/drivers/nvs.cpp | 17 +++++++++++++++++ src/tangara/input/input_device.hpp | 3 ++- src/tangara/input/input_nav_buttons.cpp | 2 +- src/tangara/input/input_nav_buttons.hpp | 2 +- src/tangara/input/input_touch_dpad.cpp | 2 +- src/tangara/input/input_touch_dpad.hpp | 2 +- src/tangara/input/input_touch_wheel.cpp | 2 +- src/tangara/input/input_touch_wheel.hpp | 2 +- src/tangara/input/input_volume_buttons.cpp | 2 +- src/tangara/input/input_volume_buttons.hpp | 2 +- src/tangara/input/lvgl_input_driver.cpp | 29 ++++++++++++++++++++++++++++- src/tangara/input/lvgl_input_driver.hpp | 2 ++ 13 files changed, 65 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp index 9725bb0f..b6192ab5 100644 --- a/src/drivers/include/drivers/nvs.hpp +++ b/src/drivers/include/drivers/nvs.hpp @@ -138,6 +138,13 @@ class NvsStorage { auto PrimaryInput() -> InputModes; auto PrimaryInput(InputModes) -> void; + enum class LockedInputModes : uint8_t { + kDisabled = 0, + }; + + auto LockedInput() -> LockedInputModes; + auto LockedInput(LockedInputModes) -> void; + auto QueueRepeatMode() -> uint8_t; auto QueueRepeatMode(uint8_t) -> void; @@ -167,6 +174,7 @@ class NvsStorage { Setting amp_cur_vol_; Setting amp_left_bias_; Setting input_mode_; + Setting locked_input_mode_; Setting output_mode_; Setting theme_; diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index 6f0d874e..a9f30042 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -34,6 +34,7 @@ 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 kKeyLockedInput[] = "in_locked"; static constexpr char kKeyScrollSensitivity[] = "scroll"; static constexpr char kKeyLockPolarity[] = "lockpol"; static constexpr char kKeyDisplayCols[] = "dispcols"; @@ -272,6 +273,7 @@ NvsStorage::NvsStorage(nvs_handle_t handle) amp_cur_vol_(kKeyAmpCurrentVolume), amp_left_bias_(kKeyAmpLeftBias), input_mode_(kKeyPrimaryInput), + locked_input_mode_(kKeyLockedInput), output_mode_(kKeyOutput), theme_{kKeyInterfaceTheme}, bt_preferred_(kKeyBluetoothPreferred), @@ -570,6 +572,21 @@ auto NvsStorage::PrimaryInput(InputModes mode) -> void { input_mode_.set(static_cast(mode)); } +auto NvsStorage::LockedInput() -> LockedInputModes { + std::lock_guard lock{mutex_}; + switch (input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { + case static_cast(LockedInputModes::kDisabled): + return LockedInputModes::kDisabled; + default: + return LockedInputModes::kDisabled; + } +} + +auto NvsStorage::LockedInput(LockedInputModes mode) -> void { + std::lock_guard lock{mutex_}; + locked_input_mode_.set(static_cast(mode)); +} + auto NvsStorage::QueueRepeatMode() -> uint8_t { std::lock_guard lock{mutex_}; return queue_repeat_mode_.get().value_or(0); diff --git a/src/tangara/input/input_device.hpp b/src/tangara/input/input_device.hpp index 7edded3e..424c0da3 100644 --- a/src/tangara/input/input_device.hpp +++ b/src/tangara/input/input_device.hpp @@ -10,6 +10,7 @@ #include #include +#include "drivers/nvs.hpp" #include "indev/lv_indev.h" #include "input/input_hook.hpp" #include "lua/property.hpp" @@ -34,7 +35,7 @@ class IInputDevice { } /* Called by the LVGL driver when controls are being locked. */ - virtual auto onLock() -> void {} + virtual auto onLock(drivers::NvsStorage::LockedInputModes) -> void {} /* Called by the LVGL driver when controls are being unlocked. */ virtual auto onUnlock() -> void {} }; diff --git a/src/tangara/input/input_nav_buttons.cpp b/src/tangara/input/input_nav_buttons.cpp index 54bef7a6..a5e10013 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() -> void { +auto NavButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { locked_ = true; } diff --git a/src/tangara/input/input_nav_buttons.hpp b/src/tangara/input/input_nav_buttons.hpp index 95d56d54..c9575fe0 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> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> 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 8ed2bdd7..25c2315b 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() -> void { +auto TouchDPad::onLock(drivers::NvsStorage::LockedInputModes mode) -> 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 d787bace..086f556e 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> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> 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 19ac5211..ea6d1b56 100644 --- a/src/tangara/input/input_touch_wheel.cpp +++ b/src/tangara/input/input_touch_wheel.cpp @@ -113,7 +113,7 @@ auto TouchWheel::triggers() return {centre_, up_, right_, down_, left_}; } -auto TouchWheel::onLock() -> void { +auto TouchWheel::onLock(drivers::NvsStorage::LockedInputModes mode) -> 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 982f89f4..e8391914 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> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> 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 7ffdfcdc..6720afae 100644 --- a/src/tangara/input/input_volume_buttons.cpp +++ b/src/tangara/input/input_volume_buttons.cpp @@ -39,7 +39,7 @@ auto VolumeButtons::triggers() return {up_, down_}; } -auto VolumeButtons::onLock() -> void { +auto VolumeButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { locked_ = true; } diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp index ffb3156b..008252cd 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> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> void override; auto onUnlock() -> void override; private: diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp index c008b007..9177f92f 100644 --- a/src/tangara/input/lvgl_input_driver.cpp +++ b/src/tangara/input/lvgl_input_driver.cpp @@ -53,6 +53,8 @@ static void focus_cb(lv_group_t* group) { instance->feedback(LV_EVENT_FOCUSED); } +namespace { + auto intToMode(int raw) -> std::optional { switch (raw) { case 0: @@ -68,6 +70,17 @@ auto intToMode(int raw) -> std::optional { } } +auto intToLockedMode(int raw) -> std::optional { + switch (raw) { + case 0: + return drivers::NvsStorage::LockedInputModes::kDisabled; + default: + return {}; + } +} + +} // namespace {} + LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory& factory) : nvs_(nvs), @@ -85,6 +98,18 @@ LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs, inputs_ = factory.createInputs(*mode); return true; }), + locked_mode_(static_cast(nvs.LockedInput()), + [&](const lua::LuaValue& val) { + if (!std::holds_alternative(val)) { + return false; + } + auto mode = intToLockedMode(std::get(val)); + if (!mode) { + return false; + } + nvs.LockedInput(*mode); + return true; + }), inputs_(factory.createInputs(nvs.PrimaryInput())), feedbacks_(factory.createFeedbacks()), is_locked_(false) { @@ -130,9 +155,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(); + device->onLock(locked_input_mode); } else { device->onUnlock(); } diff --git a/src/tangara/input/lvgl_input_driver.hpp b/src/tangara/input/lvgl_input_driver.hpp index 9b62c24d..ce950621 100644 --- a/src/tangara/input/lvgl_input_driver.hpp +++ b/src/tangara/input/lvgl_input_driver.hpp @@ -36,6 +36,7 @@ class LvglInputDriver { LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory&); auto mode() -> lua::Property& { return mode_; } + auto lockedMode() -> lua::Property& { return locked_mode_; } auto setGroup(lv_group_t*) -> void; auto read(lv_indev_data_t* data) -> void; @@ -49,6 +50,7 @@ class LvglInputDriver { DeviceFactory& factory_; lua::Property mode_; + lua::Property locked_mode_; lv_indev_t* device_; std::vector> inputs_; -- cgit v1.2.3 From 1d485c97b0c03577a40b34fb762c76e98f417fa4 Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sat, 1 Feb 2025 16:15:17 -0800 Subject: Add optional support for changing volume while locked This adds a new Controls setting for adjusting the behavior when locked, and an option for allowing volume control. --- src/drivers/include/drivers/nvs.hpp | 1 + src/drivers/nvs.cpp | 4 +++- src/tangara/input/input_volume_buttons.cpp | 10 ++++++---- src/tangara/input/input_volume_buttons.hpp | 3 ++- src/tangara/input/lvgl_input_driver.cpp | 2 ++ src/tangara/lua/lua_controls.cpp | 17 +++++++++++++++++ src/tangara/ui/ui_fsm.cpp | 1 + 7 files changed, 32 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp index b6192ab5..18bc5de6 100644 --- a/src/drivers/include/drivers/nvs.hpp +++ b/src/drivers/include/drivers/nvs.hpp @@ -140,6 +140,7 @@ class NvsStorage { enum class LockedInputModes : uint8_t { kDisabled = 0, + kVolumeOnly = 1, }; auto LockedInput() -> LockedInputModes; diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index a9f30042..f46049ad 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -574,9 +574,11 @@ auto NvsStorage::PrimaryInput(InputModes mode) -> void { auto NvsStorage::LockedInput() -> LockedInputModes { std::lock_guard lock{mutex_}; - switch (input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { + switch (locked_input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { case static_cast(LockedInputModes::kDisabled): return LockedInputModes::kDisabled; + case static_cast(LockedInputModes::kVolumeOnly): + return LockedInputModes::kVolumeOnly; default: return LockedInputModes::kDisabled; } diff --git a/src/tangara/input/input_volume_buttons.cpp b/src/tangara/input/input_volume_buttons.cpp index 6720afae..5c814ffa 100644 --- a/src/tangara/input/input_volume_buttons.cpp +++ b/src/tangara/input/input_volume_buttons.cpp @@ -15,13 +15,15 @@ VolumeButtons::VolumeButtons(drivers::IGpios& gpios) : gpios_(gpios), up_("upper", actions::volumeUp()), down_("lower", actions::volumeDown()), - locked_(false) {} + locked_() {} auto VolumeButtons::read(lv_indev_data_t* data) -> void { bool up = !gpios_.Get(drivers::IGpios::Pin::kKeyUp); bool down = !gpios_.Get(drivers::IGpios::Pin::kKeyDown); - if ((up && down) || locked_) { + bool input_disabled = locked_.has_value() && (locked_ != drivers::NvsStorage::LockedInputModes::kVolumeOnly); + + if ((up && down) || input_disabled) { up = false; down = false; } @@ -40,11 +42,11 @@ auto VolumeButtons::triggers() } auto VolumeButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { - locked_ = true; + locked_ = mode; } auto VolumeButtons::onUnlock() -> void { - locked_ = false; + locked_ = {}; } } // namespace input diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp index 008252cd..35a44390 100644 --- a/src/tangara/input/input_volume_buttons.hpp +++ b/src/tangara/input/input_volume_buttons.hpp @@ -36,7 +36,8 @@ class VolumeButtons : public IInputDevice { TriggerHooks up_; TriggerHooks down_; - bool locked_; + // When locked, this contains the active mode + std::optional locked_; }; } // namespace input diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp index 9177f92f..2859c6a8 100644 --- a/src/tangara/input/lvgl_input_driver.cpp +++ b/src/tangara/input/lvgl_input_driver.cpp @@ -74,6 +74,8 @@ auto intToLockedMode(int raw) -> std::optional int { return 1; } +static auto locked_controls_schemes(lua_State* L) -> int { + lua_newtable(L); + + lua_pushliteral(L, "Disabled"); + lua_rawseti( + L, -2, + static_cast(drivers::NvsStorage::LockedInputModes::kDisabled)); + + lua_pushliteral(L, "Volume Only"); + lua_rawseti( + L, -2, + static_cast(drivers::NvsStorage::LockedInputModes::kVolumeOnly)); + + return 1; +} + static const struct luaL_Reg kControlsFuncs[] = {{"schemes", controls_schemes}, + {"locked_schemes", locked_controls_schemes}, {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 4a54d974..1823f780 100644 --- a/src/tangara/ui/ui_fsm.cpp +++ b/src/tangara/ui/ui_fsm.cpp @@ -667,6 +667,7 @@ void Lua::entry() { "controls", { {"scheme", &sInput->mode()}, + {"locked_scheme", &sInput->lockedMode()}, {"lock_switch", &sLockSwitch}, {"hooks", [&](lua_State* L) { return sInput->pushHooks(L); }}, }); -- cgit v1.2.3 From 546daf71c1b04284848c4b5edfbaa3c5b4a284f4 Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sun, 2 Feb 2025 00:30:59 -0800 Subject: Persist locked control mode setting --- src/drivers/nvs.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index f46049ad..02a0058b 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -302,6 +302,7 @@ auto NvsStorage::Read() -> void { amp_cur_vol_.read(handle_); amp_left_bias_.read(handle_); input_mode_.read(handle_); + locked_input_mode_.read(handle_); output_mode_.read(handle_); theme_.read(handle_); bt_preferred_.read(handle_); @@ -325,6 +326,7 @@ auto NvsStorage::Write() -> bool { amp_cur_vol_.write(handle_); amp_left_bias_.write(handle_); input_mode_.write(handle_); + locked_input_mode_.write(handle_); output_mode_.write(handle_); theme_.write(handle_); bt_preferred_.write(handle_); -- cgit v1.2.3