fully implement Key press handeling in HAL for esp32 hardware and switch hardware to use the refactored UI
make UI add widgets on button presses as a demo
This commit is contained in:
parent
7434f0b4da
commit
4a5c83c8b9
8 changed files with 113 additions and 29 deletions
|
@ -35,17 +35,19 @@ public:
|
|||
Aux1,
|
||||
Aux2,
|
||||
Aux3,
|
||||
Aux4
|
||||
Aux4,
|
||||
INVALID
|
||||
};
|
||||
|
||||
class KeyEvent {
|
||||
public:
|
||||
enum class Type { Press, Release };
|
||||
enum class Type { Press, Release, INVALID };
|
||||
|
||||
KeyEvent() = default;
|
||||
KeyEvent(const KeyId aId, const Type aType) : mId(aId), mType(aType) {}
|
||||
|
||||
const KeyId mId;
|
||||
const Type mType;
|
||||
KeyId mId = KeyId::INVALID;
|
||||
Type mType = Type::INVALID;
|
||||
};
|
||||
|
||||
KeyPressAbstract();
|
||||
|
|
|
@ -1,25 +1,61 @@
|
|||
#include "keys.hpp"
|
||||
|
||||
Keys::Keys() {}
|
||||
void Keys::HandleKeyPresses(){
|
||||
Keys::Keys() {
|
||||
static constexpr auto MaxQueueableKeyPresses = 5;
|
||||
mKeyPressQueueHandle = xQueueCreate(MaxQueueableKeyPresses, sizeof(KeyEvent));
|
||||
xTaskCreate(KeyGrabberTask, "KeyGrabber", 1024, this, 1, &mKeyGrabbingTask);
|
||||
xTaskCreate(KeyProccessor, "KeyProccessor", 4096, this, 1, &mKeyHandlingTask);
|
||||
}
|
||||
|
||||
void Keys::KeyGrabberTask(void *aSelf) {
|
||||
auto self = reinterpret_cast<Keys *>(aSelf);
|
||||
while (true) {
|
||||
self->GrabKeys();
|
||||
vTaskDelay(5 / portTICK_PERIOD_MS); // 5 ms between key grabs
|
||||
}
|
||||
}
|
||||
void Keys::KeyProccessor(void *aSelf) {
|
||||
auto self = reinterpret_cast<Keys *>(aSelf);
|
||||
while (true) {
|
||||
self->HandleKeyPresses();
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void Keys::HandleKeyPresses() {
|
||||
KeyPressAbstract::KeyEvent eventToHandle;
|
||||
while (xQueueReceive(mKeyPressQueueHandle, &eventToHandle, 0) == pdTRUE) {
|
||||
if (mKeyEventHandler) {
|
||||
mKeyEventHandler(eventToHandle);
|
||||
}
|
||||
}
|
||||
};
|
||||
void Keys::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent){
|
||||
|
||||
void Keys::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) {
|
||||
BaseType_t higherPriorityTaskAwoke;
|
||||
xQueueSendFromISR(mKeyPressQueueHandle, &aJustOccuredKeyEvent,
|
||||
&higherPriorityTaskAwoke);
|
||||
};
|
||||
|
||||
void Keys::GrabKeys() {
|
||||
customKeypad.getKey(); // Populate key list
|
||||
for (int i = 0; i < LIST_MAX;
|
||||
i++) { // Handle multiple keys (Not really necessary in this case)
|
||||
if (!customKeypad.getKeys()) {
|
||||
return; // no activity return early.
|
||||
}
|
||||
for (int i = 0; i < LIST_MAX; i++) {
|
||||
if (customKeypad.key[i].kstate == PRESSED ||
|
||||
customKeypad.key[i].kstate == HOLD) {
|
||||
customKeypad.key[i].kstate == RELEASED) {
|
||||
// May need to think about resetting sleep timer in key handler....
|
||||
// standbyTimer =
|
||||
// sleepTimeout; // Reset the sleep timer when a button is pressed
|
||||
int keyCode = customKeypad.key[i].kcode;
|
||||
// Queue Keys here!!
|
||||
Serial.println(customKeypad.key[i].kchar);
|
||||
// sleepTimeout; // Reset the sleep timer when a button is
|
||||
// pressed
|
||||
auto eventType = customKeypad.key[i].kstate == PRESSED
|
||||
? KeyEvent::Type::Press
|
||||
: KeyEvent::Type::Release;
|
||||
const auto keyChar = customKeypad.key[i].kchar;
|
||||
auto stateChange = customKeypad.key[i].stateChanged;
|
||||
if (charKeyToKeyIds.count(keyChar) > 0 && stateChange) {
|
||||
QueueKeyEvent(KeyEvent(charKeyToKeyIds.at(keyChar), eventType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#include "KeyPressAbstract.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include <Keypad.h> // modified for inverted logic
|
||||
#include <map>
|
||||
|
||||
class Keys : public KeyPressAbstract {
|
||||
public:
|
||||
|
@ -13,6 +14,9 @@ protected:
|
|||
void GrabKeys();
|
||||
|
||||
private:
|
||||
static void KeyGrabberTask(void *aSelf);
|
||||
static void KeyProccessor(void *aSelf);
|
||||
|
||||
QueueHandle_t mKeyPressQueueHandle;
|
||||
TaskHandle_t mKeyGrabbingTask;
|
||||
TaskHandle_t mKeyHandlingTask;
|
||||
|
@ -23,11 +27,46 @@ private:
|
|||
// define the symbols on the buttons of the keypads
|
||||
char hexaKeys[ROWS][COLS] = {
|
||||
{'s', '^', '-', 'm', 'r'}, // source, channel+, Volume-, mute, record
|
||||
{'i', 'r', '+', 'k', 'd'}, // info, right, Volume+, OK, down
|
||||
{'i', 'R', '+', 'k', 'd'}, // info, right, Volume+, OK, down
|
||||
{'4', 'v', '1', '3', '2'}, // blue, channel-, red, yellow, green
|
||||
{'>', 'o', 'b', 'u', 'l'}, // forward, off, back, up, left
|
||||
{'>', 'o', 'b', 'u', 'L'}, // forward, off, back, up, left
|
||||
{'?', 'p', 'c', '<', '='} // ?, play, config, rewind, stop
|
||||
};
|
||||
// TODO what is '?' lol
|
||||
|
||||
// TODO Should be able to optomize this out by reordering Ids at some point
|
||||
// or even using interrupts to trigger key press queueing
|
||||
static inline const std::map<char, KeyId> charKeyToKeyIds{
|
||||
{'o', KeyId::Power},
|
||||
// Top 4 Buttons left to right
|
||||
{'=', KeyId::Stop},
|
||||
{'<', KeyId::Rewind},
|
||||
{'p', KeyId::Play},
|
||||
{'>', KeyId::FastForward},
|
||||
// Buttons around D Pad
|
||||
{'c', KeyId::Menu},
|
||||
{'i', KeyId::Info},
|
||||
{'b', KeyId::Back},
|
||||
{'s', KeyId::Source},
|
||||
// D Pad
|
||||
{'u', KeyId::Up},
|
||||
{'d', KeyId::Down},
|
||||
{'L', KeyId::Left},
|
||||
{'R', KeyId::Right},
|
||||
{'k', KeyId::Center},
|
||||
// Volume Channel and 2 between
|
||||
{'+', KeyId::VolUp},
|
||||
{'-', KeyId::VolDown},
|
||||
{'m', KeyId::Mute},
|
||||
{'r', KeyId::Record},
|
||||
{'^', KeyId::ChannelUp},
|
||||
{'v', KeyId::ChannelDown},
|
||||
// Bottom 4 buttons left to right
|
||||
{'1', KeyId::Aux1},
|
||||
{'2', KeyId::Aux2},
|
||||
{'3', KeyId::Aux3},
|
||||
{'4', KeyId::Aux4}};
|
||||
|
||||
byte rowPins[ROWS] = {SW_A, SW_B, SW_C, SW_D,
|
||||
SW_E}; // connect to the row pinouts of the keypad
|
||||
byte colPins[COLS] = {SW_1, SW_2, SW_3, SW_4,
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
using namespace UI::Page;
|
||||
|
||||
SettingsPage::SettingsPage() : Base(ID::Pages::Settings) {
|
||||
SettingsPage::SettingsPage(std::shared_ptr<HardwareAbstract> aHardware)
|
||||
: Base(ID::Pages::Settings), mHardware(aHardware) {
|
||||
SetBgColor(lv_color_make(255, 0, 0));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "HardwareAbstract.hpp"
|
||||
#include "PageBase.hpp"
|
||||
|
||||
namespace UI::Page {
|
||||
class SettingsPage : public Base {
|
||||
public:
|
||||
SettingsPage();
|
||||
SettingsPage(std::shared_ptr<HardwareAbstract> aHardware = nullptr);
|
||||
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
|
@ -13,5 +14,6 @@ protected:
|
|||
void OnShow() override;
|
||||
|
||||
std::vector<Widget::Base *> sliders;
|
||||
std::shared_ptr<HardwareAbstract> mHardware;
|
||||
};
|
||||
} // namespace UI::Page
|
||||
|
|
|
@ -3,16 +3,17 @@
|
|||
|
||||
using namespace UI::Screen;
|
||||
|
||||
HomeScreen::HomeScreen()
|
||||
: Base(UI::ID::Screens::Home), mTabView(ID(ID::Pages::INVALID_PAGE_ID)) {
|
||||
HomeScreen::HomeScreen(std::shared_ptr<HardwareAbstract> aHardware)
|
||||
: Base(UI::ID::Screens::Home), mHardware(aHardware),
|
||||
mTabView(ID(ID::Pages::INVALID_PAGE_ID)) {
|
||||
SetBgColor(lv_color_black());
|
||||
SetPushAnimation(LV_SCR_LOAD_ANIM_FADE_IN);
|
||||
|
||||
AddElement(&mTabView); // Adds Tabview to Homescreen
|
||||
|
||||
// Adds pages to the Tab view
|
||||
mTabView.AddTab(std::make_unique<Page::SettingsPage>(), "Settings");
|
||||
mTabView.AddTab(std::make_unique<Page::SettingsPage>(), "Settings1");
|
||||
mTabView.AddTab(std::make_unique<Page::SettingsPage>(aHardware), "Settings");
|
||||
mTabView.AddTab(std::make_unique<Page::SettingsPage>(aHardware), "Settings1");
|
||||
}
|
||||
|
||||
void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "PageBase.hpp"
|
||||
#include "ScreenBase.hpp"
|
||||
#include "TabView.hpp"
|
||||
|
@ -7,7 +8,7 @@ namespace UI::Screen {
|
|||
|
||||
class HomeScreen : public Base {
|
||||
public:
|
||||
HomeScreen();
|
||||
HomeScreen(std::shared_ptr<HardwareAbstract> aHardware = nullptr);
|
||||
|
||||
void SetBgColor(lv_color_t value,
|
||||
lv_style_selector_t selector = LV_PART_MAIN) override;
|
||||
|
@ -19,6 +20,7 @@ protected:
|
|||
|
||||
private:
|
||||
Page::TabView mTabView;
|
||||
std::shared_ptr<HardwareAbstract> mHardware = nullptr;
|
||||
};
|
||||
|
||||
} // namespace UI::Screen
|
|
@ -1,24 +1,25 @@
|
|||
// OMOTE firmware for ESP32
|
||||
// 2023 Maximilian Kern
|
||||
|
||||
#include "BasicUI.hpp"
|
||||
#include "HardwareRevX.hpp"
|
||||
#include "OmoteUI.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include <lvgl.h>
|
||||
|
||||
std::shared_ptr<HardwareRevX> hal = nullptr;
|
||||
std::shared_ptr<UI::UIBase> ui = nullptr;
|
||||
|
||||
void setup() {
|
||||
hal = HardwareRevX::getInstance();
|
||||
hal->init();
|
||||
|
||||
auto ui = UI::Basic::OmoteUI::getInstance(hal);
|
||||
ui->layout_UI();
|
||||
auto ui = UI::BasicUI(hal);
|
||||
// ui->layout_UI();
|
||||
|
||||
lv_timer_handler(); // Run the LVGL UI once before the loop takes over
|
||||
}
|
||||
|
||||
void loop() {
|
||||
HardwareRevX::getInstance()->loopHandler();
|
||||
UI::Basic::OmoteUI::getInstance()->loopHandler();
|
||||
hal->loopHandler();
|
||||
ui->loopHandler();
|
||||
}
|
Loading…
Add table
Reference in a new issue