Add KeyPress Abstract and a KeyPress Simulator

as beginning stages for forwarding key events to the UI.
This commit is contained in:
MatthewColvin 2023-09-29 11:52:48 -05:00
parent 0796176a0e
commit 414f711373
7 changed files with 192 additions and 6 deletions

View file

@ -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<BatteryInterface> battery() = 0;
virtual std::shared_ptr<BatteryInterface> battery() = 0;
virtual std::shared_ptr<DisplayAbstract> display() = 0;
virtual std::shared_ptr<wifiHandlerInterface> wifi() = 0;
virtual std::shared_ptr<KeyPressAbstract> 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:
};

View file

@ -0,0 +1,5 @@
#include "KeyPressAbstract.hpp"
KeyPressAbstract::KeyPressAbstract(
std::function<bool(KeyPressAbstract::KeyEvent)> aKeyEventHandler)
: mKeyEventHandler(std::move(aKeyEventHandler)) {}

View file

@ -0,0 +1,70 @@
#pragma once
#include "Notification.hpp"
#include "SPSCQueueInterface.hpp"
#include <memory>
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<bool(KeyEvent)> 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<bool(KeyEvent)> mKeyEventHandler;
};

View file

@ -12,7 +12,8 @@ HardwareSimulator::HardwareSimulator()
}),
mBattery(std::make_shared<BatterySimulator>()),
mDisplay(SDLDisplay::getInstance()),
mWifiHandler(std::make_shared<wifiHandlerSim>()) {
mWifiHandler(std::make_shared<wifiHandlerSim>()),
mKeys(std::make_shared<KeyPressSim>([](auto keypress) { return true; })) {
mHardwareStatusTitleUpdate = std::thread([this] {
int dataToShow = 0;
while (true) {
@ -46,6 +47,7 @@ std::shared_ptr<DisplayAbstract> HardwareSimulator::display() {
std::shared_ptr<wifiHandlerInterface> HardwareSimulator::wifi() {
return mWifiHandler;
}
std::shared_ptr<KeyPressAbstract> HardwareSimulator::keys() { return mKeys; }
char HardwareSimulator::getCurrentDevice() { return 0; }

View file

@ -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<BatteryInterface> battery() override;
virtual std::shared_ptr<DisplayAbstract> display() override;
virtual std::shared_ptr<wifiHandlerInterface> wifi() override;
virtual std::shared_ptr<KeyPressAbstract> keys() override;
virtual char getCurrentDevice() override;
virtual void setCurrentDevice(char currentDevice) override;
@ -40,4 +42,5 @@ private:
std::shared_ptr<BatterySimulator> mBattery;
std::shared_ptr<SDLDisplay> mDisplay;
std::shared_ptr<wifiHandlerSim> mWifiHandler;
std::shared_ptr<KeyPressSim> mKeys;
};

View file

@ -0,0 +1,48 @@
#include "KeyPressSim.hpp"
#include "SimulatorSPSCQueue.hpp"
#include <memory>
KeyPressSim::KeyPressSim(
std::function<bool(KeyPressAbstract::KeyEvent)> 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);
};

View file

@ -0,0 +1,57 @@
#include "KeyPressAbstract.hpp"
#include "SDL2/SDL.h"
#include <map>
#include <mutex>
#include <queue>
#include <thread>
class KeyPressSim : public KeyPressAbstract {
public:
static constexpr auto MaxQueueableKeyEvents = 3;
KeyPressSim(std::function<bool(KeyPressAbstract::KeyEvent)> aKeyHandler);
void GrabKeys();
void HandleKeyPresses() override;
void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) override;
private:
std::thread mKeyGrabberThread;
std::thread mKeyHandlerThread;
std::queue<KeyEvent> mKeyEventQueue;
std::mutex mQueueGaurd;
using Key = KeyPressAbstract::KeyId;
static inline const std::map<SDL_Keycode, KeyPressAbstract::KeyId> 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}};
};