#include "bottom_half.h" #include "inputs.hpp" #include static uint8_t reverse_4_bits(uint8_t value) { return static_cast(((value & 0x1) << 3) | ((value & 0x2) << 1) | ((value & 0x4) >> 1) | ((value & 0x8) >> 3)); } static KeypadKey map_input_keypad_key(InputKeypadKey key) { switch (key) { case InputKeypadKey::K0: return KeypadKey::k0; case InputKeypadKey::K1: return KeypadKey::k1; case InputKeypadKey::K2: return KeypadKey::k2; case InputKeypadKey::K3: return KeypadKey::k3; case InputKeypadKey::K4: return KeypadKey::k4; case InputKeypadKey::K5: return KeypadKey::k5; case InputKeypadKey::K6: return KeypadKey::k6; case InputKeypadKey::K7: return KeypadKey::k7; case InputKeypadKey::K8: return KeypadKey::k8; case InputKeypadKey::K9: return KeypadKey::k9; case InputKeypadKey::A: return KeypadKey::ka; case InputKeypadKey::B: return KeypadKey::kb; case InputKeypadKey::C: return KeypadKey::kc; case InputKeypadKey::D: return KeypadKey::kd; case InputKeypadKey::STAR: return KeypadKey::star; case InputKeypadKey::POUND: return KeypadKey::pound; default: return KeypadKey::k0; } } static uint8_t get_fingerprint_touch_state() { InputsState current = InputsController::get_input_state(); return static_cast((current.touch_state >> 4) & 0x1); } static bool touch_state_initialized = false; static bool touch_state_last = false; static bool update_fingerprint_transition(bool want_pressed) { bool current = get_fingerprint_touch_state(); if (!touch_state_initialized) { touch_state_last = current; touch_state_initialized = true; return false; } bool transition = want_pressed ? (current && !touch_state_last) : (!current && touch_state_last); touch_state_last = current; return transition; } static std::array pending_switch_flips; static size_t pending_switch_flip_count = 0; static void push_pending_switch_flip(const SwitchFlip& event) { if (pending_switch_flip_count < pending_switch_flips.size()) { pending_switch_flips[pending_switch_flip_count++] = event; return; } // Drop the oldest event if the buffer is full. for (size_t i = 1; i < pending_switch_flips.size(); ++i) { pending_switch_flips[i - 1] = pending_switch_flips[i]; } pending_switch_flips.back() = event; } static bool pop_pending_switch_flip(bool want_up, SwitchFlip& out) { for (size_t i = 0; i < pending_switch_flip_count; ++i) { if (pending_switch_flips[i].is_up() == want_up) { out = pending_switch_flips[i]; for (size_t j = i + 1; j < pending_switch_flip_count; ++j) { pending_switch_flips[j - 1] = pending_switch_flips[j]; } --pending_switch_flip_count; return true; } } return false; } static void clear_pending_switch_flips() { pending_switch_flip_count = 0; } static std::array pending_switch_touches; static size_t pending_switch_touch_count = 0; static void push_pending_switch_touch(const SwitchTouch& event) { if (pending_switch_touch_count < pending_switch_touches.size()) { pending_switch_touches[pending_switch_touch_count++] = event; return; } for (size_t i = 1; i < pending_switch_touches.size(); ++i) { pending_switch_touches[i - 1] = pending_switch_touches[i]; } pending_switch_touches.back() = event; } static bool pop_pending_switch_touch(bool want_touched, SwitchTouch& out) { for (size_t i = 0; i < pending_switch_touch_count; ++i) { if (pending_switch_touches[i].is_touched() == want_touched) { out = pending_switch_touches[i]; for (size_t j = i + 1; j < pending_switch_touch_count; ++j) { pending_switch_touches[j - 1] = pending_switch_touches[j]; } --pending_switch_touch_count; return true; } } return false; } static void clear_pending_switch_touches() { pending_switch_touch_count = 0; } void init_bottom_half() { init_expander(); clear_all_pressed_released(); } void clear_all_pressed_released() { InputsController::clear_all_events(); clear_pending_switch_flips(); clear_pending_switch_touches(); touch_state_initialized = false; } bool get_keypad_pressed(KeypadKey* kp) { auto opt = InputsController::get_keypad_press(); if (!opt.has_value()) { return false; } if (kp != nullptr) { *kp = map_input_keypad_key(opt.value()); } return true; } bool get_keypad_released(KeypadKey* kp) { auto opt = InputsController::get_keypad_release(); if (!opt.has_value()) { return false; } if (kp != nullptr) { *kp = map_input_keypad_key(opt.value()); } return true; } char char_of_keypad_key(KeypadKey kp) { switch (kp) { case KeypadKey::k1: return '1'; case KeypadKey::k2: return '2'; case KeypadKey::k3: return '3'; case KeypadKey::k4: return '4'; case KeypadKey::k5: return '5'; case KeypadKey::k6: return '6'; case KeypadKey::k7: return '7'; case KeypadKey::k8: return '8'; case KeypadKey::k9: return '9'; case KeypadKey::k0: return '0'; case KeypadKey::ka: return 'A'; case KeypadKey::kb: return 'B'; case KeypadKey::kc: return 'C'; case KeypadKey::kd: return 'D'; case KeypadKey::star: return '*'; case KeypadKey::pound: return '#'; default: return ' '; } } static bool take_button(ButtonKey* button, std::optional