diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-10-04 10:18:31 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-10-04 10:18:31 +1100 |
| commit | 5c04e2ad8d14616ce3ca09b658d25bab3d8d2460 (patch) | |
| tree | 411b269ca33ddadb0a95ac74a171b53a5fc7ac07 /src/ui/encoder_input.cpp | |
| parent | c851b789faf71d0ef2092ae7d8cd3190c13d85c9 (diff) | |
| download | tangara-fw-5c04e2ad8d14616ce3ca09b658d25bab3d8d2460.tar.gz | |
Neaten up the various kinds of inputs, and move volumes to The New Way
Diffstat (limited to 'src/ui/encoder_input.cpp')
| -rw-r--r-- | src/ui/encoder_input.cpp | 243 |
1 files changed, 173 insertions, 70 deletions
diff --git a/src/ui/encoder_input.cpp b/src/ui/encoder_input.cpp index 9aa5d29a..0345665b 100644 --- a/src/ui/encoder_input.cpp +++ b/src/ui/encoder_input.cpp @@ -9,13 +9,16 @@ #include <sys/_stdint.h> #include <memory> +#include "audio_events.hpp" #include "core/lv_group.h" #include "esp_timer.h" +#include "event_queue.hpp" #include "gpios.hpp" #include "hal/lv_hal_indev.h" #include "nvs.hpp" #include "relative_wheel.hpp" #include "touchwheel.hpp" +#include "ui_events.hpp" constexpr int kDPadAngleThreshold = 20; constexpr int kLongPressDelayMs = 500; @@ -70,83 +73,139 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void { } // Check each button. - HandleKey(Keys::kVolumeUp, now_ms, !gpios_.Get(drivers::IGpios::Pin::kKeyUp)); - HandleKey(Keys::kVolumeDown, now_ms, - !gpios_.Get(drivers::IGpios::Pin::kKeyDown)); + HandleKeyState(Keys::kVolumeUp, now_ms, + !gpios_.Get(drivers::IGpios::Pin::kKeyUp)); + HandleKeyState(Keys::kVolumeDown, now_ms, + !gpios_.Get(drivers::IGpios::Pin::kKeyDown)); drivers::TouchWheelData wheel_data = raw_wheel_.GetTouchWheelData(); - HandleKey(Keys::kTouchWheel, now_ms, wheel_data.is_wheel_touched); - HandleKey(Keys::kTouchWheelCenter, now_ms, wheel_data.is_button_touched); + HandleKeyState(Keys::kTouchWheel, now_ms, wheel_data.is_wheel_touched); + HandleKeyState(Keys::kTouchWheelCenter, now_ms, wheel_data.is_button_touched); - HandleKey( + HandleKeyState( Keys::kDirectionalUp, now_ms, wheel_data.is_wheel_touched && IsAngleWithin(wheel_data.wheel_position, 0, kDPadAngleThreshold)); - HandleKey( + HandleKeyState( Keys::kDirectionalLeft, now_ms, wheel_data.is_wheel_touched && IsAngleWithin(wheel_data.wheel_position, 63, kDPadAngleThreshold)); - HandleKey( + HandleKeyState( Keys::kDirectionalDown, now_ms, wheel_data.is_wheel_touched && IsAngleWithin(wheel_data.wheel_position, 127, kDPadAngleThreshold)); - HandleKey( + HandleKeyState( Keys::kDirectionalRight, now_ms, wheel_data.is_wheel_touched && IsAngleWithin(wheel_data.wheel_position, 189, kDPadAngleThreshold)); // We now have enough information to give LVGL its update. + Trigger trigger; switch (mode_) { case drivers::NvsStorage::InputModes::kButtonsOnly: data->state = LV_INDEV_STATE_RELEASED; - if (ShortPressTrigger(Keys::kVolumeUp)) { - data->enc_diff = -1; - } else if (ShortPressTrigger(Keys::kVolumeDown)) { - data->enc_diff = 1; - } else if (LongPressTrigger(Keys::kVolumeDown, now_ms)) { - data->state = LV_INDEV_STATE_PRESSED; - } else if (LongPressTrigger(Keys::kVolumeUp, now_ms)) { - // TODO: Back button event + + trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + data->enc_diff = -1; + break; + case Trigger::kLongPress: + events::Ui().Dispatch(internal::BackPressed{}); + break; + } + + trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + data->enc_diff = 1; + break; + case Trigger::kLongPress: + data->state = LV_INDEV_STATE_PRESSED; + break; } + break; case drivers::NvsStorage::InputModes::kButtonsWithWheel: - data->state = ShortPressTrigger(Keys::kTouchWheel) - ? LV_INDEV_STATE_PRESSED - : LV_INDEV_STATE_RELEASED; - if (ShortPressTriggerRepeating(Keys::kVolumeUp, now_ms)) { + trigger = TriggerKey(Keys::kTouchWheel, KeyStyle::kLongPress, now_ms); + data->state = trigger == Trigger::kClick ? LV_INDEV_STATE_PRESSED + : LV_INDEV_STATE_RELEASED; + + trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { data->enc_diff = scroller_->AddInput(now_ms, -1); - } else if (ShortPressTriggerRepeating(Keys::kVolumeDown, now_ms)) { + } + + trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { data->enc_diff = scroller_->AddInput(now_ms, 1); } + // Cancel scrolling if the buttons are released. if (!touch_time_ms_.contains(Keys::kVolumeDown) && !touch_time_ms_.contains(Keys::kVolumeUp)) { data->enc_diff = scroller_->AddInput(now_ms, 0); } - // TODO: Long-press events. + break; case drivers::NvsStorage::InputModes::kDirectionalWheel: - data->state = ShortPressTrigger(Keys::kTouchWheelCenter) - ? LV_INDEV_STATE_PRESSED - : LV_INDEV_STATE_RELEASED; - if (!ShortPressTriggerRepeating(Keys::kTouchWheel, now_ms)) { - break; - } - if (ShortPressTriggerRepeating(Keys::kDirectionalUp, now_ms)) { + trigger = + TriggerKey(Keys::kTouchWheelCenter, KeyStyle::kLongPress, now_ms); + data->state = trigger == Trigger::kClick ? LV_INDEV_STATE_PRESSED + : LV_INDEV_STATE_RELEASED; + + trigger = TriggerKey(Keys::kDirectionalUp, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { data->enc_diff = scroller_->AddInput(now_ms, -1); - } else if (ShortPressTriggerRepeating(Keys::kDirectionalDown, now_ms)) { + } + + trigger = TriggerKey(Keys::kDirectionalDown, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { data->enc_diff = scroller_->AddInput(now_ms, 1); - } else if (ShortPressTrigger(Keys::kDirectionalRight)) { + } + + trigger = TriggerKey(Keys::kDirectionalLeft, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { + events::Ui().Dispatch(internal::BackPressed{}); + } + + trigger = TriggerKey(Keys::kDirectionalRight, KeyStyle::kRepeat, now_ms); + if (trigger == Trigger::kClick) { // TODO: ??? - } else if (ShortPressTrigger(Keys::kDirectionalLeft)) { - // TODO: Back button event. } + // Cancel scrolling if the touchpad is released. if (!touch_time_ms_.contains(Keys::kDirectionalUp) && !touch_time_ms_.contains(Keys::kDirectionalDown)) { data->enc_diff = scroller_->AddInput(now_ms, 0); } - // TODO: Long-press events. + + trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + events::Audio().Dispatch(audio::StepUpVolume{}); + break; + case Trigger::kLongPress: + break; + } + + trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + events::Audio().Dispatch(audio::StepDownVolume{}); + break; + case Trigger::kLongPress: + break; + } + break; case drivers::NvsStorage::InputModes::kRotatingWheel: if (!raw_wheel_.GetTouchWheelData().is_wheel_touched) { @@ -156,53 +215,97 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void { } else { data->enc_diff = 0; } - data->state = relative_wheel_->is_clicking() ? LV_INDEV_STATE_PRESSED - : LV_INDEV_STATE_RELEASED; - // TODO: Long-press events. + + trigger = + TriggerKey(Keys::kTouchWheelCenter, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + data->state = LV_INDEV_STATE_RELEASED; + break; + case Trigger::kClick: + data->state = LV_INDEV_STATE_PRESSED; + break; + case Trigger::kLongPress: + // TODO: ??? + data->state = LV_INDEV_STATE_PRESSED; + break; + } + + trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + events::Audio().Dispatch(audio::StepUpVolume{}); + break; + case Trigger::kLongPress: + break; + } + + trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms); + switch (trigger) { + case Trigger::kNone: + break; + case Trigger::kClick: + events::Audio().Dispatch(audio::StepDownVolume{}); + break; + case Trigger::kLongPress: + break; + } + break; } - - // TODO: Apply inertia / acceleration. } -auto EncoderInput::HandleKey(Keys key, uint64_t ms, bool clicked) -> void { - if (!clicked) { - touch_time_ms_.erase(key); - short_press_fired_.erase(key); - long_press_fired_.erase(key); +auto EncoderInput::HandleKeyState(Keys key, uint64_t ms, bool clicked) -> void { + if (clicked) { + if (!touch_time_ms_.contains(key)) { + // Key was just pressed + touch_time_ms_[key] = ms; + just_released_.erase(key); + fired_.erase(key); + } return; } - if (!touch_time_ms_.contains(key)) { - touch_time_ms_[key] = ms; - } -} -auto EncoderInput::ShortPressTrigger(Keys key) -> bool { - if (touch_time_ms_.contains(key) && !short_press_fired_.contains(key)) { - short_press_fired_[key] = true; - return true; + // Key is not clicked. + if (touch_time_ms_.contains(key)) { + // Key was just released. + just_released_.insert(key); + touch_time_ms_.erase(key); } - return false; } -auto EncoderInput::ShortPressTriggerRepeating(Keys key, uint64_t ms) -> bool { - if (touch_time_ms_.contains(key) && - (!short_press_fired_.contains(key) || - ms - touch_time_ms_[key] >= kRepeatDelayMs)) { - touch_time_ms_[key] = ms; - short_press_fired_[key] = true; - return true; - } - return false; -} +auto EncoderInput::TriggerKey(Keys key, KeyStyle s, uint64_t ms) -> Trigger { + if (s == KeyStyle::kRepeat) { + bool may_repeat = fired_.contains(key) && touch_time_ms_.contains(key) && + ms - touch_time_ms_[key] >= kRepeatDelayMs; -auto EncoderInput::LongPressTrigger(Keys key, uint64_t ms) -> bool { - if (touch_time_ms_.contains(key) && !long_press_fired_.contains(key) && - ms - touch_time_ms_[key] >= kLongPressDelayMs) { - long_press_fired_[key] = true; - return true; + // Repeatable keys trigger on press. + if (touch_time_ms_.contains(key) && (!fired_.contains(key) || may_repeat)) { + fired_.insert(key); + return Trigger::kClick; + } else { + return Trigger::kNone; + } + } else if (s == KeyStyle::kLongPress) { + // Long press keys trigger on release, or after holding for a delay. + if (just_released_.contains(key)) { + just_released_.erase(key); + if (!fired_.contains(key)) { + fired_.insert(key); + return Trigger::kClick; + } + } + if (touch_time_ms_.contains(key) && + ms - touch_time_ms_[key] >= kLongPressDelayMs && + !fired_.contains(key)) { + fired_.insert(key); + return Trigger::kLongPress; + } } - return false; + + return Trigger::kNone; } auto Scroller::AddInput(uint64_t ms, int direction) -> int { |
