From 414f711373819cdb6f01d0a9ea691efe51fea981 Mon Sep 17 00:00:00 2001 From: MatthewColvin Date: Fri, 29 Sep 2023 11:52:48 -0500 Subject: [PATCH] Add KeyPress Abstract and a KeyPress Simulator as beginning stages for forwarding key events to the UI. --- Platformio/HAL/HardwareAbstract.hpp | 11 +-- .../HAL/HardwareModules/KeyPressAbstract.cpp | 5 ++ .../HAL/HardwareModules/KeyPressAbstract.hpp | 70 +++++++++++++++++++ .../Targets/Simulator/HardwareSimulator.cpp | 4 +- .../Targets/Simulator/HardwareSimulator.hpp | 3 + .../HAL/Targets/Simulator/KeyPressSim.cpp | 48 +++++++++++++ .../HAL/Targets/Simulator/KeyPressSim.hpp | 57 +++++++++++++++ 7 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 Platformio/HAL/HardwareModules/KeyPressAbstract.cpp create mode 100644 Platformio/HAL/HardwareModules/KeyPressAbstract.hpp create mode 100644 Platformio/HAL/Targets/Simulator/KeyPressSim.cpp create mode 100644 Platformio/HAL/Targets/Simulator/KeyPressSim.hpp diff --git a/Platformio/HAL/HardwareAbstract.hpp b/Platformio/HAL/HardwareAbstract.hpp index 8d163eb..e927873 100644 --- a/Platformio/HAL/HardwareAbstract.hpp +++ b/Platformio/HAL/HardwareAbstract.hpp @@ -3,6 +3,7 @@ #pragma once #include "BatteryInterface.h" #include "DisplayAbstract.h" +#include "KeyPressAbstract.hpp" #include "wifiHandlerInterface.h" #include "Notification.hpp" @@ -16,24 +17,24 @@ public: /// @brief Override in order to do setup of hardware devices post construction virtual void init() = 0; - /// @brief Override to allow printing of a message for debugging /// @param message - Debug message - virtual void debugPrint(const char* fmt, ...) = 0; + virtual void debugPrint(const char *fmt, ...) = 0; - virtual std::shared_ptr battery() = 0; + virtual std::shared_ptr battery() = 0; virtual std::shared_ptr display() = 0; virtual std::shared_ptr wifi() = 0; + virtual std::shared_ptr keys() = 0; virtual char getCurrentDevice() = 0; virtual void setCurrentDevice(char currentDevice) = 0; - + virtual bool getWakeupByIMUEnabled() = 0; virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) = 0; virtual uint16_t getSleepTimeout() = 0; virtual void setSleepTimeout(uint16_t sleepTimeout) = 0; - protected: +protected: }; \ No newline at end of file diff --git a/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp b/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp new file mode 100644 index 0000000..5b12d38 --- /dev/null +++ b/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp @@ -0,0 +1,5 @@ +#include "KeyPressAbstract.hpp" + +KeyPressAbstract::KeyPressAbstract( + std::function aKeyEventHandler) + : mKeyEventHandler(std::move(aKeyEventHandler)) {} diff --git a/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp b/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp new file mode 100644 index 0000000..1bf6ede --- /dev/null +++ b/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp @@ -0,0 +1,70 @@ +#pragma once +#include "Notification.hpp" +#include "SPSCQueueInterface.hpp" + +#include +class KeyPressAbstract { +public: + // Keys from Top Down left to right. + enum class KeyId { + Power, + // Top 4 Buttons left to right + Stop, + Rewind, + Play, + FastForward, + // Buttons around D Pad + Menu, + Info, + Back, + Source, + // D Pad + Up, + Down, + Left, + Right, + Center, + // Volume Channel and 2 between + VolUp, + VolDown, + Mute, + Record, + ChannelUp, + ChannelDown, + // Bottom 4 buttons left to right + Aux1, + Aux2, + Aux3, + Aux4 + }; + + class KeyEvent { + public: + enum class Type { Press, Release }; + + KeyEvent(const KeyId aId, const Type aType) : mId(aId), mType(aType) {} + + const KeyId mId; + const Type mType; + }; + /// @brief When Constructing pass a callable to be ran for Handling + /// KeyEvents + /// @param aKeyEventHandler + KeyPressAbstract(std::function aKeyEventHandler); + +protected: + /// @brief Function ment to be called regularly to allow + /// proccesssing of key presses by calling mKeyEventHandler + /// best case this is done on a seprate thread/task + /// since it could take a while to handle a KeyPress + virtual void HandleKeyPresses() = 0; + + /// @brief Function to queue up Key events to be handled later on by + /// HandleKeyPresses() hopefully on a seprate thread or task + /// This function should be implemented in a way that makes it ISR + /// safe + /// @param aJustOccuredKeyEvent - A Key even that just occured + virtual void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) = 0; + + std::function mKeyEventHandler; +}; \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp index 063c1f1..74eae44 100644 --- a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp +++ b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp @@ -12,7 +12,8 @@ HardwareSimulator::HardwareSimulator() }), mBattery(std::make_shared()), mDisplay(SDLDisplay::getInstance()), - mWifiHandler(std::make_shared()) { + mWifiHandler(std::make_shared()), + mKeys(std::make_shared([](auto keypress) { return true; })) { mHardwareStatusTitleUpdate = std::thread([this] { int dataToShow = 0; while (true) { @@ -46,6 +47,7 @@ std::shared_ptr HardwareSimulator::display() { std::shared_ptr HardwareSimulator::wifi() { return mWifiHandler; } +std::shared_ptr HardwareSimulator::keys() { return mKeys; } char HardwareSimulator::getCurrentDevice() { return 0; } diff --git a/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp b/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp index 41a6b95..1a68818 100644 --- a/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp +++ b/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp @@ -1,6 +1,7 @@ #pragma once #include "HardwareAbstract.hpp" +#include "KeyPressSim.hpp" #include "SDLDisplay.hpp" #include "batterySimulator.hpp" #include "wifiHandlerSim.hpp" @@ -23,6 +24,7 @@ public: virtual std::shared_ptr battery() override; virtual std::shared_ptr display() override; virtual std::shared_ptr wifi() override; + virtual std::shared_ptr keys() override; virtual char getCurrentDevice() override; virtual void setCurrentDevice(char currentDevice) override; @@ -40,4 +42,5 @@ private: std::shared_ptr mBattery; std::shared_ptr mDisplay; std::shared_ptr mWifiHandler; + std::shared_ptr mKeys; }; diff --git a/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp b/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp new file mode 100644 index 0000000..1beab8c --- /dev/null +++ b/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp @@ -0,0 +1,48 @@ +#include "KeyPressSim.hpp" +#include "SimulatorSPSCQueue.hpp" + +#include + +KeyPressSim::KeyPressSim( + std::function aKeyHandler) + : KeyPressAbstract(std::move(aKeyHandler)), mKeyGrabberThread([this] { + while (true) { + HandleKeyPresses(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + }), + mKeyHandlerThread([this] { + while (true) { + GrabKeys(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + }){}; + +void KeyPressSim::GrabKeys() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) { + auto keyEventType = event.type == SDL_KEYDOWN ? KeyEvent::Type::Press + : KeyEvent::Type::Release; + const auto SDLK_key = event.key.keysym.sym; + if (KeyMap.count(SDLK_key) > 0) { + QueueKeyEvent(KeyEvent(KeyMap.at(SDLK_key), keyEventType)); + } + } + } +}; + +void KeyPressSim::HandleKeyPresses() { + std::lock_guard lock(mQueueGaurd); + while (!mKeyEventQueue.empty()) { + printf(mKeyEventQueue.front().mType == KeyEvent::Type::Release ? "release" + : "press"); + mKeyEventHandler(mKeyEventQueue.front()); + mKeyEventQueue.pop(); + } +}; + +void KeyPressSim::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) { + std::lock_guard lock(mQueueGaurd); + mKeyEventQueue.push(aJustOccuredKeyEvent); +}; diff --git a/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp b/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp new file mode 100644 index 0000000..24c5d69 --- /dev/null +++ b/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp @@ -0,0 +1,57 @@ +#include "KeyPressAbstract.hpp" +#include "SDL2/SDL.h" + +#include +#include +#include +#include + +class KeyPressSim : public KeyPressAbstract { +public: + static constexpr auto MaxQueueableKeyEvents = 3; + + KeyPressSim(std::function aKeyHandler); + + void GrabKeys(); + void HandleKeyPresses() override; + void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) override; + +private: + std::thread mKeyGrabberThread; + std::thread mKeyHandlerThread; + std::queue mKeyEventQueue; + std::mutex mQueueGaurd; + + using Key = KeyPressAbstract::KeyId; + static inline const std::map KeyMap{ + {SDLK_p, Key::Power}, + // Video Control row + {SDLK_5, Key::Stop}, + {SDLK_6, Key::Rewind}, + {SDLK_7, Key::Play}, + {SDLK_8, Key::FastForward}, + // D-Pad + {SDLK_UP, Key::Up}, + {SDLK_DOWN, Key::Down}, + {SDLK_LEFT, Key::Left}, + {SDLK_RIGHT, Key::Right}, + {SDLK_SPACE, Key::Center}, + // General Keys + {SDLK_h, Key::Menu}, + {SDLK_j, Key::Info}, + {SDLK_l, Key::Back}, + {SDLK_k, Key::Source}, + // Volume/ Channel UP and down + {SDLK_w, Key::VolUp}, + {SDLK_s, Key::VolDown}, + {SDLK_e, Key::ChannelUp}, + {SDLK_d, Key::ChannelDown}, + // Mute & record + {SDLK_x, Key::Mute}, + {SDLK_c, Key::Record}, + // Aux Keys + {SDLK_1, Key::Aux1}, + {SDLK_2, Key::Aux2}, + {SDLK_3, Key::Aux3}, + {SDLK_4, Key::Aux4}}; +}; \ No newline at end of file