UI refactor (#50)
This commit is contained in:
parent
59897369ec
commit
7c9a0623fd
95 changed files with 4726 additions and 2307 deletions
2
Platformio/.vscode/settings.json
vendored
2
Platformio/.vscode/settings.json
vendored
|
@ -81,6 +81,6 @@
|
|||
"variant": "cpp"
|
||||
},
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO",
|
||||
"editor.formatOnSave": false,
|
||||
"editor.formatOnSave": true,
|
||||
"idf.portWin": "COM8"
|
||||
}
|
|
@ -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 processing in main thread
|
||||
virtual void loopHandler() = 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:
|
||||
|
||||
};
|
20
Platformio/HAL/HardwareFactory.cpp
Normal file
20
Platformio/HAL/HardwareFactory.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "HardwareFactory.hpp"
|
||||
|
||||
#if OMOTE_SIM
|
||||
#include "HardwareSimulator.hpp"
|
||||
#endif
|
||||
|
||||
#if OMOTE_ESP32
|
||||
#include "HardwareRevX.hpp"
|
||||
#endif
|
||||
|
||||
#if OMOTE_SIM
|
||||
std::unique_ptr<HardwareAbstract> HardwareFactory::mHardware =
|
||||
std::make_unique<HardwareSimulator>();
|
||||
#endif
|
||||
#if OMOTE_ESP32
|
||||
std::unique_ptr<HardwareAbstract> HardwareFactory::mHardware =
|
||||
std::make_unique<HardwareRevX>();
|
||||
#endif
|
||||
|
||||
HardwareAbstract &HardwareFactory::getAbstract() { return *mHardware; }
|
11
Platformio/HAL/HardwareFactory.hpp
Normal file
11
Platformio/HAL/HardwareFactory.hpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "HardwareAbstract.hpp"
|
||||
#include <memory>
|
||||
/**
|
||||
* @brief The HardwareFactory is responsible for making the
|
||||
*/
|
||||
class HardwareFactory {
|
||||
public:
|
||||
static HardwareAbstract &getAbstract();
|
||||
|
||||
static std::unique_ptr<HardwareAbstract> mHardware;
|
||||
};
|
8
Platformio/HAL/HardwareModules/KeyPressAbstract.cpp
Normal file
8
Platformio/HAL/HardwareModules/KeyPressAbstract.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "KeyPressAbstract.hpp"
|
||||
|
||||
KeyPressAbstract::KeyPressAbstract() {}
|
||||
|
||||
void KeyPressAbstract::RegisterKeyPressHandler(
|
||||
std::function<bool(KeyPressAbstract::KeyEvent)> aKeyEventHandler) {
|
||||
mKeyEventHandler = std::move(aKeyEventHandler);
|
||||
}
|
73
Platformio/HAL/HardwareModules/KeyPressAbstract.hpp
Normal file
73
Platformio/HAL/HardwareModules/KeyPressAbstract.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
#include "Notification.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,
|
||||
INVALID
|
||||
};
|
||||
|
||||
class KeyEvent {
|
||||
public:
|
||||
enum class Type { Press, Release, INVALID };
|
||||
|
||||
KeyEvent() = default;
|
||||
KeyEvent(const KeyId aId, const Type aType) : mId(aId), mType(aType) {}
|
||||
|
||||
KeyId mId = KeyId::INVALID;
|
||||
Type mType = Type::INVALID;
|
||||
};
|
||||
|
||||
KeyPressAbstract();
|
||||
|
||||
/// @brief Register a SINGLE handler to be used for proccessing keys
|
||||
/// @param aKeyEventHandler - Callable the Handles KeyEvent
|
||||
void RegisterKeyPressHandler(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;
|
||||
};
|
|
@ -1,25 +1,54 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
typedef struct {
|
||||
std::string ssid;
|
||||
int rssi;
|
||||
} WifiInfo;
|
||||
class wifiHandlerInterface {
|
||||
public:
|
||||
wifiHandlerInterface() = default;
|
||||
struct WifiInfo {
|
||||
WifiInfo() = default;
|
||||
WifiInfo(std::string aSsid, int aRssi) : ssid(aSsid), rssi(aRssi) {}
|
||||
|
||||
typedef struct {
|
||||
bool isConnected;
|
||||
std::string IP;
|
||||
std::string ssid;
|
||||
}wifiStatus;
|
||||
std::string ssid = "";
|
||||
int rssi = 0;
|
||||
};
|
||||
|
||||
class wifiHandlerInterface{
|
||||
public:
|
||||
virtual bool isAvailable() = 0;
|
||||
virtual void scan() = 0;
|
||||
virtual void connect(std::shared_ptr<std::string> ssid, std::shared_ptr<std::string> password) = 0;
|
||||
virtual void onScanDone(std::function<void (std::shared_ptr<std::vector<WifiInfo>>)> function) = 0;
|
||||
virtual void onStatusUpdate(std::function<void (std::shared_ptr<wifiStatus>)> function) = 0;
|
||||
virtual void begin() = 0;
|
||||
struct wifiStatus {
|
||||
wifiStatus() = default;
|
||||
wifiStatus(bool aConnected, std::string aIp, std::string aSsid)
|
||||
: isConnected(aConnected), IP(aIp), ssid(aSsid){};
|
||||
|
||||
bool isConnected = false;
|
||||
std::string IP = "";
|
||||
std::string ssid = "";
|
||||
};
|
||||
|
||||
typedef std::vector<WifiInfo> ScanDoneDataTy;
|
||||
typedef Notification<ScanDoneDataTy> ScanNotificationTy;
|
||||
|
||||
/// @brief Initialize the wifi handler
|
||||
virtual void begin() = 0;
|
||||
/// @brief Trigger a scan scan for wifi networks
|
||||
virtual void scan() = 0;
|
||||
/// @brief Attempt a connection to the wifi using the provided credentials
|
||||
virtual void connect(std::string ssid, std::string password) = 0;
|
||||
/// @brief Get the status of the current wifi connection
|
||||
virtual wifiStatus GetStatus() = 0;
|
||||
|
||||
// Register for Scan Notification to handle when scans are completed
|
||||
std::shared_ptr<ScanNotificationTy> ScanCompleteNotification() {
|
||||
return mScanNotification;
|
||||
};
|
||||
|
||||
// Register for Status notifications to handle changes in status
|
||||
std::shared_ptr<Notification<wifiStatus>> WifiStatusNotification() {
|
||||
return mStatusUpdate;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ScanNotificationTy> mScanNotification =
|
||||
std::make_shared<ScanNotificationTy>();
|
||||
std::shared_ptr<Notification<wifiStatus>> mStatusUpdate =
|
||||
std::make_shared<Notification<wifiStatus>>();
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
// OMOTE Hardware Abstraction
|
||||
// 2023 Matthew Colvin
|
||||
|
||||
#pragma once
|
||||
#include <lvgl.h>
|
||||
#include <string>
|
||||
|
||||
class HardwareInterface {
|
||||
public:
|
||||
struct batteryStatus {
|
||||
/// @brief Percent of battery remaining (0-100]
|
||||
int percentage;
|
||||
/// @brief Voltage of battery in millivolts
|
||||
int voltage;
|
||||
/// @brief True - Battery is Charging
|
||||
/// False - Battery discharging
|
||||
bool isCharging;
|
||||
};
|
||||
|
||||
HardwareInterface() = default;
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void sendIR() = 0;
|
||||
virtual void MQTTPublish(const char *topic, const char *payload) = 0;
|
||||
virtual batteryStatus getBatteryPercentage() = 0;
|
||||
virtual void debugPrint(std::string message) = 0;
|
||||
};
|
|
@ -1,29 +1,90 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
template <class... notifyData>
|
||||
class Notification{
|
||||
public:
|
||||
typedef std::function<void(notifyData...)> HandlerTy;
|
||||
template <class... notifyData> class Handler;
|
||||
template <class... notifyData> class Notification {
|
||||
friend class Handler<notifyData...>;
|
||||
|
||||
Notification() = default;
|
||||
void onNotify(HandlerTy aHandler);
|
||||
void notify(notifyData... notifySendData);
|
||||
public:
|
||||
typedef std::function<void(notifyData...)> HandlerTy;
|
||||
typedef int HandlerID;
|
||||
|
||||
private:
|
||||
std::vector<HandlerTy> mFunctionHandlers;
|
||||
Notification() { mIdMaker = 0; };
|
||||
void notify(notifyData... notifySendData);
|
||||
|
||||
protected:
|
||||
HandlerID onNotify(HandlerTy aHandler);
|
||||
void unregister(HandlerID aHandler);
|
||||
|
||||
private:
|
||||
std::map<HandlerID, HandlerTy> mFunctionHandlers;
|
||||
HandlerID mIdMaker;
|
||||
};
|
||||
|
||||
|
||||
template <class... handlerData>
|
||||
void Notification<handlerData...>::onNotify(HandlerTy aHandler){
|
||||
mFunctionHandlers.push_back(std::move(aHandler));
|
||||
int Notification<handlerData...>::onNotify(HandlerTy aHandler) {
|
||||
if (aHandler) {
|
||||
mFunctionHandlers[++mIdMaker] = std::move(aHandler);
|
||||
return mIdMaker;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
template <class... outboundData>
|
||||
void Notification<outboundData...>::notify(outboundData... notifySendData){
|
||||
for (auto handler : mFunctionHandlers){
|
||||
handler(notifySendData...);
|
||||
void Notification<outboundData...>::notify(outboundData... notifySendData) {
|
||||
for (auto handler : mFunctionHandlers) {
|
||||
handler.second(notifySendData...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... handlerData>
|
||||
void Notification<handlerData...>::unregister(HandlerID aHandlerId) {
|
||||
auto handlerToUnRegister =
|
||||
std::find_if(mFunctionHandlers.begin(), mFunctionHandlers.end(),
|
||||
[aHandlerId](auto registeredHandler) {
|
||||
return aHandlerId == registeredHandler.first;
|
||||
});
|
||||
if (handlerToUnRegister != mFunctionHandlers.end()) {
|
||||
mFunctionHandlers.erase(handlerToUnRegister);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... notifyData> class Handler {
|
||||
public:
|
||||
typedef std::function<void(notifyData...)> callableTy;
|
||||
void operator=(Handler &other) = delete;
|
||||
|
||||
Handler() = default;
|
||||
Handler(std::shared_ptr<Notification<notifyData...>> aNotification,
|
||||
callableTy aCallable = nullptr)
|
||||
: mNotification(aNotification),
|
||||
mHandlerId(aNotification->onNotify(aCallable)) {}
|
||||
|
||||
virtual ~Handler() {
|
||||
if (mHandlerId >= 0) {
|
||||
mNotification->unregister(mHandlerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(callableTy aHandler) {
|
||||
if (mHandlerId >= 0) {
|
||||
mNotification->unregister(mHandlerId);
|
||||
mHandlerId = -1;
|
||||
}
|
||||
if (aHandler) {
|
||||
mHandlerId = mNotification->onNotify(aHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetNotification(std::shared_ptr<Notification<notifyData...>> aNotification) {
|
||||
mNotification = aNotification;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Notification<notifyData...>> mNotification = nullptr;
|
||||
int mHandlerId = -1;
|
||||
};
|
|
@ -2,8 +2,6 @@
|
|||
#include "display.hpp"
|
||||
#include "wifihandler.hpp"
|
||||
|
||||
std::shared_ptr<HardwareRevX> HardwareRevX::mInstance = nullptr;
|
||||
|
||||
void HardwareRevX::initIO() {
|
||||
// Button Pin Definition
|
||||
pinMode(SW_1, OUTPUT);
|
||||
|
@ -50,9 +48,7 @@ void HardwareRevX::initIO() {
|
|||
gpio_deep_sleep_hold_dis();
|
||||
}
|
||||
|
||||
HardwareRevX::HardwareRevX():
|
||||
HardwareAbstract(){
|
||||
}
|
||||
HardwareRevX::HardwareRevX() : HardwareAbstract() {}
|
||||
|
||||
HardwareRevX::WakeReason getWakeReason() {
|
||||
// Find out wakeup cause
|
||||
|
@ -74,11 +70,15 @@ void HardwareRevX::init() {
|
|||
Serial.begin(115200);
|
||||
|
||||
mDisplay = Display::getInstance();
|
||||
mBattery = std::make_shared<Battery>(ADC_BAT,CRG_STAT);
|
||||
mBattery = std::make_shared<Battery>(ADC_BAT, CRG_STAT);
|
||||
mWifiHandler = wifiHandler::getInstance();
|
||||
mKeys = std::make_shared<Keys>();
|
||||
restorePreferences();
|
||||
|
||||
mDisplay->onTouch([this]([[maybe_unused]] auto touchPoint){ standbyTimer = this->getSleepTimeout();});
|
||||
mTouchHandler.SetNotification(mDisplay->TouchNotification());
|
||||
mTouchHandler = [this]([[maybe_unused]] auto touchPoint) {
|
||||
standbyTimer = this->getSleepTimeout();
|
||||
};
|
||||
|
||||
setupIMU();
|
||||
setupIR();
|
||||
|
@ -86,37 +86,26 @@ void HardwareRevX::init() {
|
|||
debugPrint("Finished Hardware Setup in %d", millis());
|
||||
}
|
||||
|
||||
void HardwareRevX::debugPrint(const char* fmt, ...)
|
||||
{
|
||||
void HardwareRevX::debugPrint(const char *fmt, ...) {
|
||||
char result[100];
|
||||
va_list arguments;
|
||||
|
||||
va_start(arguments, fmt);
|
||||
vsnprintf(result, 100, fmt, arguments);
|
||||
va_end (arguments);
|
||||
va_end(arguments);
|
||||
|
||||
Serial.print(result);
|
||||
}
|
||||
|
||||
std::shared_ptr<HardwareRevX> HardwareRevX::getInstance(){
|
||||
if (!mInstance) {
|
||||
mInstance = std::shared_ptr<HardwareRevX>(new HardwareRevX());
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
std::shared_ptr<wifiHandlerInterface> HardwareRevX::wifi()
|
||||
{
|
||||
std::shared_ptr<wifiHandlerInterface> HardwareRevX::wifi() {
|
||||
return mWifiHandler;
|
||||
}
|
||||
|
||||
std::shared_ptr<BatteryInterface> HardwareRevX::battery(){
|
||||
return mBattery;
|
||||
}
|
||||
std::shared_ptr<BatteryInterface> HardwareRevX::battery() { return mBattery; }
|
||||
|
||||
std::shared_ptr<DisplayAbstract> HardwareRevX::display(){
|
||||
return mDisplay;
|
||||
}
|
||||
std::shared_ptr<DisplayAbstract> HardwareRevX::display() { return mDisplay; }
|
||||
|
||||
std::shared_ptr<KeyPressAbstract> HardwareRevX::keys() { return mKeys; }
|
||||
|
||||
void HardwareRevX::activityDetection() {
|
||||
static int accXold;
|
||||
|
@ -142,27 +131,21 @@ void HardwareRevX::activityDetection() {
|
|||
accZold = accZ;
|
||||
}
|
||||
|
||||
char HardwareRevX::getCurrentDevice(){
|
||||
return currentDevice;
|
||||
}
|
||||
char HardwareRevX::getCurrentDevice() { return currentDevice; }
|
||||
|
||||
void HardwareRevX::setCurrentDevice(char currentDevice){
|
||||
void HardwareRevX::setCurrentDevice(char currentDevice) {
|
||||
this->currentDevice = currentDevice;
|
||||
}
|
||||
|
||||
bool HardwareRevX::getWakeupByIMUEnabled(){
|
||||
return wakeupByIMUEnabled;
|
||||
}
|
||||
bool HardwareRevX::getWakeupByIMUEnabled() { return wakeupByIMUEnabled; }
|
||||
|
||||
void HardwareRevX::setWakeupByIMUEnabled(bool wakeupByIMUEnabled){
|
||||
void HardwareRevX::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) {
|
||||
this->wakeupByIMUEnabled = wakeupByIMUEnabled;
|
||||
}
|
||||
|
||||
uint16_t HardwareRevX::getSleepTimeout(){
|
||||
return sleepTimeout;
|
||||
}
|
||||
uint16_t HardwareRevX::getSleepTimeout() { return sleepTimeout; }
|
||||
|
||||
void HardwareRevX::setSleepTimeout(uint16_t sleepTimeout){
|
||||
void HardwareRevX::setSleepTimeout(uint16_t sleepTimeout) {
|
||||
this->sleepTimeout = sleepTimeout;
|
||||
standbyTimer = sleepTimeout;
|
||||
}
|
||||
|
@ -287,7 +270,7 @@ void HardwareRevX::restorePreferences() {
|
|||
currentDevice = preferences.getUChar("currentDevice");
|
||||
sleepTimeout = preferences.getUInt("sleepTimeout");
|
||||
// setting the default to prevent a 0ms sleep timeout
|
||||
if(sleepTimeout == 0){
|
||||
if (sleepTimeout == 0) {
|
||||
sleepTimeout = SLEEP_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +303,7 @@ void HardwareRevX::startTasks() {}
|
|||
|
||||
void HardwareRevX::loopHandler() {
|
||||
standbyTimer < 2000 ? mDisplay->sleep() : mDisplay->wake();
|
||||
|
||||
|
||||
// TODO move to debug task
|
||||
// Blink debug LED at 1 Hz
|
||||
digitalWrite(USER_LED, millis() % 1000 > 500);
|
||||
|
@ -335,31 +318,4 @@ void HardwareRevX::loopHandler() {
|
|||
}
|
||||
IMUTaskTimer = millis();
|
||||
}
|
||||
|
||||
// Keypad Handling
|
||||
customKeypad.getKey(); // Populate key list
|
||||
for (int i = 0; i < LIST_MAX;
|
||||
i++) { // Handle multiple keys (Not really necessary in this case)
|
||||
if (customKeypad.key[i].kstate == PRESSED ||
|
||||
customKeypad.key[i].kstate == HOLD) {
|
||||
standbyTimer =
|
||||
sleepTimeout; // Reset the sleep timer when a button is pressed
|
||||
int keyCode = customKeypad.key[i].kcode;
|
||||
Serial.println(customKeypad.key[i].kchar);
|
||||
// Send IR codes depending on the current device (tabview page)
|
||||
if (currentDevice == 1) {
|
||||
IrSender.sendRC5(IrSender.encodeRC5X(
|
||||
0x00, keyMapTechnisat[keyCode / ROWS][keyCode % ROWS]));
|
||||
} else if (currentDevice == 2) {
|
||||
IrSender.sendSony((keyCode / ROWS) * (keyCode % ROWS), 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
// IR Test
|
||||
// tft.drawString("IR Command: ", 10, 90, 1);
|
||||
// decode_results results;
|
||||
// if (IrReceiver.decode(&results)) {
|
||||
// IrReceiver.resume(); // Enable receiving of the next value
|
||||
//} //tft.drawString(String(results.command) + " ", 80, 90, 1);
|
||||
//
|
||||
}
|
|
@ -2,44 +2,44 @@
|
|||
#include "SparkFunLIS3DH.h"
|
||||
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "lvgl.h"
|
||||
#include "battery.hpp"
|
||||
#include "lvgl.h"
|
||||
#include "wifihandler.hpp"
|
||||
#include <Arduino.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRsend.h>
|
||||
#include <IRutils.h>
|
||||
#include <Keypad.h> // modified for inverted logic
|
||||
#include <Preferences.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "wifihandler.hpp"
|
||||
|
||||
|
||||
|
||||
#include "omoteconfig.h"
|
||||
|
||||
#include "BatteryInterface.h"
|
||||
#include "wifiHandlerInterface.h"
|
||||
#include "display.hpp"
|
||||
#include "keys.hpp"
|
||||
#include "wifiHandlerInterface.h"
|
||||
|
||||
class HardwareRevX : public HardwareAbstract {
|
||||
public:
|
||||
enum class WakeReason { RESET, IMU, KEYPAD };
|
||||
|
||||
static std::shared_ptr<HardwareRevX> getInstance();
|
||||
static std::weak_ptr<HardwareRevX> getRefrence() { return getInstance(); }
|
||||
HardwareRevX();
|
||||
|
||||
// HardwareAbstract
|
||||
virtual void init() override;
|
||||
virtual void debugPrint(const char* fmt, ...) override;
|
||||
virtual void debugPrint(const char *fmt, ...) override;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
virtual bool getWakeupByIMUEnabled() override;
|
||||
virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ public:
|
|||
|
||||
/// @brief To be ran in loop out in main
|
||||
// TODO move to a freertos task
|
||||
void loopHandler();
|
||||
void loopHandler() override;
|
||||
|
||||
protected:
|
||||
// Init Functions to setup hardware
|
||||
void initIO();
|
||||
|
@ -65,11 +66,10 @@ protected:
|
|||
void startTasks();
|
||||
|
||||
private:
|
||||
HardwareRevX();
|
||||
|
||||
std::shared_ptr<Battery> mBattery;
|
||||
std::shared_ptr<Display> mDisplay;
|
||||
std::shared_ptr<wifiHandler> mWifiHandler;
|
||||
std::shared_ptr<Keys> mKeys;
|
||||
// IMU Motion Detection
|
||||
LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
|
||||
int standbyTimer = SLEEP_TIMEOUT;
|
||||
|
@ -86,32 +86,6 @@ private:
|
|||
IRsend IrSender = IRsend(IR_LED, true);
|
||||
IRrecv IrReceiver = IRrecv(IR_RX);
|
||||
|
||||
|
||||
// Keypad declarations
|
||||
static const byte ROWS = 5; // four rows
|
||||
static const byte COLS = 5; // four columns
|
||||
// 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
|
||||
{'4', 'v', '1', '3', '2'}, // blue, channel-, red, yellow, green
|
||||
{'>', 'o', 'b', 'u', 'l'}, // forward, off, back, up, left
|
||||
{'?', 'p', 'c', '<', '='} // ?, play, config, rewind, stop
|
||||
};
|
||||
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,
|
||||
SW_5}; // connect to the column pinouts of the keypad
|
||||
Keypad customKeypad =
|
||||
Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
|
||||
|
||||
byte keyMapTechnisat[ROWS][COLS] = {{0x69, 0x20, 0x11, 0x0D, 0x56},
|
||||
{0x4F, 0x37, 0x10, 0x57, 0x51},
|
||||
{0x6E, 0x21, 0x6B, 0x6D, 0x6C},
|
||||
{0x34, 0x0C, 0x22, 0x50, 0x55},
|
||||
{'?', 0x35, 0x2F, 0x32, 0x36}};
|
||||
byte virtualKeyMapTechnisat[10] = {0x1, 0x2, 0x3, 0x4, 0x5,
|
||||
0x6, 0x7, 0x8, 0x9, 0x0};
|
||||
|
||||
static std::shared_ptr<HardwareRevX> mInstance;
|
||||
Handler<TS_Point> mTouchHandler;
|
||||
};
|
|
@ -1,43 +1,39 @@
|
|||
|
||||
#include "display.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include "Wire.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "omoteconfig.h"
|
||||
|
||||
std::shared_ptr<Display> Display::getInstance()
|
||||
{
|
||||
if (DisplayAbstract::mInstance == nullptr)
|
||||
{
|
||||
DisplayAbstract::mInstance = std::shared_ptr<Display>(new Display(LCD_BL, LCD_EN));
|
||||
}
|
||||
return std::static_pointer_cast<Display>(mInstance);
|
||||
std::shared_ptr<Display> Display::getInstance() {
|
||||
if (DisplayAbstract::mInstance == nullptr) {
|
||||
DisplayAbstract::mInstance =
|
||||
std::shared_ptr<Display>(new Display(LCD_BL, LCD_EN));
|
||||
}
|
||||
return std::static_pointer_cast<Display>(mInstance);
|
||||
}
|
||||
|
||||
Display::Display(int backlight_pin, int enable_pin): DisplayAbstract(),
|
||||
mBacklightPin(backlight_pin),
|
||||
mEnablePin(enable_pin),
|
||||
tft(TFT_eSPI()),
|
||||
touch(Adafruit_FT6206())
|
||||
{
|
||||
pinMode(mEnablePin, OUTPUT);
|
||||
digitalWrite(mEnablePin, HIGH);
|
||||
pinMode(mBacklightPin, OUTPUT);
|
||||
digitalWrite(mBacklightPin, HIGH);
|
||||
Display::Display(int backlight_pin, int enable_pin)
|
||||
: DisplayAbstract(), mBacklightPin(backlight_pin), mEnablePin(enable_pin),
|
||||
tft(TFT_eSPI()), touch(Adafruit_FT6206()) {
|
||||
pinMode(mEnablePin, OUTPUT);
|
||||
digitalWrite(mEnablePin, HIGH);
|
||||
pinMode(mBacklightPin, OUTPUT);
|
||||
digitalWrite(mBacklightPin, HIGH);
|
||||
|
||||
setupBacklight(); // This eliminates the flash of the backlight
|
||||
setupBacklight(); // This eliminates the flash of the backlight
|
||||
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for(int i = 0; i < 100; i++){
|
||||
digitalWrite(this->mEnablePin, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(this->mEnablePin, LOW); // LCD Logic on
|
||||
}
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for (int i = 0; i < 100; i++) {
|
||||
digitalWrite(this->mEnablePin, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(this->mEnablePin, LOW); // LCD Logic on
|
||||
}
|
||||
|
||||
setupTFT();
|
||||
setupTouchScreen();
|
||||
mFadeTaskMutex = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(mFadeTaskMutex);
|
||||
setupTFT();
|
||||
setupTouchScreen();
|
||||
mFadeTaskMutex = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(mFadeTaskMutex);
|
||||
}
|
||||
|
||||
void Display::setupBacklight() {
|
||||
|
@ -62,10 +58,6 @@ void Display::setupBacklight() {
|
|||
ledc_timer_config(&ledc_timer);
|
||||
}
|
||||
|
||||
void Display::onTouch(Notification<TS_Point>::HandlerTy aTouchHandler){
|
||||
mTouchEvent.onNotify(std::move(aTouchHandler));
|
||||
}
|
||||
|
||||
void Display::setupTFT() {
|
||||
delay(100);
|
||||
tft.init();
|
||||
|
@ -75,25 +67,22 @@ void Display::setupTFT() {
|
|||
tft.setSwapBytes(true);
|
||||
}
|
||||
|
||||
void Display::setupTouchScreen(){
|
||||
// Configure i2c pins and set frequency to 400kHz
|
||||
Wire.begin(SDA, SCL, 400000);
|
||||
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
void Display::setupTouchScreen() {
|
||||
// Configure i2c pins and set frequency to 400kHz
|
||||
Wire.begin(TFT_SDA, TFT_SCL, 400000);
|
||||
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
}
|
||||
|
||||
void Display::setBrightness(uint8_t brightness)
|
||||
{
|
||||
void Display::setBrightness(uint8_t brightness) {
|
||||
mAwakeBrightness = brightness;
|
||||
Serial.print("Set Brightness:");
|
||||
Serial.println(mAwakeBrightness);
|
||||
startFade();
|
||||
}
|
||||
|
||||
uint8_t Display::getBrightness(){
|
||||
return mAwakeBrightness;
|
||||
}
|
||||
uint8_t Display::getBrightness() { return mAwakeBrightness; }
|
||||
|
||||
void Display::setCurrentBrightness(uint8_t brightness){
|
||||
void Display::setCurrentBrightness(uint8_t brightness) {
|
||||
mBrightness = brightness;
|
||||
auto duty = static_cast<int>(mBrightness);
|
||||
ledcWrite(LCD_BACKLIGHT_LEDC_CHANNEL, duty);
|
||||
|
@ -101,25 +90,24 @@ void Display::setCurrentBrightness(uint8_t brightness){
|
|||
// Serial.println(mBrightness);
|
||||
}
|
||||
|
||||
void Display::turnOff()
|
||||
{
|
||||
digitalWrite(this->mBacklightPin, HIGH);
|
||||
digitalWrite(this->mEnablePin, HIGH);
|
||||
pinMode(this->mBacklightPin, INPUT);
|
||||
pinMode(this->mEnablePin, INPUT);
|
||||
gpio_hold_en((gpio_num_t) mBacklightPin);
|
||||
gpio_hold_en((gpio_num_t) mEnablePin);
|
||||
void Display::turnOff() {
|
||||
digitalWrite(this->mBacklightPin, HIGH);
|
||||
digitalWrite(this->mEnablePin, HIGH);
|
||||
pinMode(this->mBacklightPin, INPUT);
|
||||
pinMode(this->mEnablePin, INPUT);
|
||||
gpio_hold_en((gpio_num_t)mBacklightPin);
|
||||
gpio_hold_en((gpio_num_t)mEnablePin);
|
||||
}
|
||||
|
||||
void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){
|
||||
// int16_t touchX, touchY;
|
||||
void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
|
||||
// int16_t touchX, touchY;
|
||||
touchPoint = touch.getPoint();
|
||||
int16_t touchX = touchPoint.x;
|
||||
int16_t touchY = touchPoint.y;
|
||||
bool touched = false;
|
||||
if ((touchX > 0) || (touchY > 0)) {
|
||||
touched = true;
|
||||
mTouchEvent.notify(touchPoint);
|
||||
mTouchEvent->notify(touchPoint);
|
||||
}
|
||||
|
||||
if (!touched) {
|
||||
|
@ -140,48 +128,50 @@ void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){
|
|||
}
|
||||
}
|
||||
|
||||
void Display::fadeImpl(void* ){
|
||||
void Display::fadeImpl(void *) {
|
||||
bool fadeDone = false;
|
||||
while(!fadeDone){
|
||||
while (!fadeDone) {
|
||||
fadeDone = getInstance()->fade();
|
||||
vTaskDelay(3 / portTICK_PERIOD_MS); // 3 miliseconds between steps
|
||||
// 0 - 255 will take about .75 seconds to fade up.
|
||||
vTaskDelay(3 / portTICK_PERIOD_MS); // 3 miliseconds between steps
|
||||
// 0 - 255 will take about .75 seconds to fade up.
|
||||
}
|
||||
|
||||
xSemaphoreTake(getInstance()->mFadeTaskMutex,portMAX_DELAY);
|
||||
|
||||
xSemaphoreTake(getInstance()->mFadeTaskMutex, portMAX_DELAY);
|
||||
getInstance()->mDisplayFadeTask = nullptr;
|
||||
xSemaphoreGive(getInstance()->mFadeTaskMutex);
|
||||
|
||||
vTaskDelete(nullptr); // Delete Fade Task
|
||||
}
|
||||
|
||||
bool Display::fade(){
|
||||
//Early return no fade needed.
|
||||
if (mBrightness == mAwakeBrightness ||
|
||||
isAsleep && mBrightness == 0){return true;}
|
||||
|
||||
bool fadeDown = isAsleep || mBrightness > mAwakeBrightness;
|
||||
if (fadeDown){
|
||||
bool Display::fade() {
|
||||
// Early return no fade needed.
|
||||
if (mBrightness == mAwakeBrightness || isAsleep && mBrightness == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fadeDown = isAsleep || mBrightness > mAwakeBrightness;
|
||||
if (fadeDown) {
|
||||
setCurrentBrightness(mBrightness - 1);
|
||||
auto setPoint = isAsleep ? 0 : mAwakeBrightness;
|
||||
return mBrightness == setPoint;
|
||||
}else{
|
||||
} else {
|
||||
setCurrentBrightness(mBrightness + 1);
|
||||
return mBrightness == mAwakeBrightness;
|
||||
}
|
||||
}
|
||||
|
||||
void Display::startFade(){
|
||||
xSemaphoreTake(mFadeTaskMutex,portMAX_DELAY);
|
||||
void Display::startFade() {
|
||||
xSemaphoreTake(mFadeTaskMutex, portMAX_DELAY);
|
||||
// Only Create Task if it is needed
|
||||
if(mDisplayFadeTask == nullptr){
|
||||
xTaskCreate(&Display::fadeImpl, "Display Fade Task",
|
||||
1024, nullptr, 5, &mDisplayFadeTask);
|
||||
if (mDisplayFadeTask == nullptr) {
|
||||
xTaskCreate(&Display::fadeImpl, "Display Fade Task", 1024, nullptr, 5,
|
||||
&mDisplayFadeTask);
|
||||
}
|
||||
xSemaphoreGive(mFadeTaskMutex);
|
||||
}
|
||||
|
||||
void Display::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
|
||||
void Display::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p) {
|
||||
uint32_t w = (area->x2 - area->x1 + 1);
|
||||
uint32_t h = (area->y2 - area->y1 + 1);
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include "DisplayAbstract.h"
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "Notification.hpp"
|
||||
#include <Adafruit_FT6206.h>
|
||||
#include <memory>
|
||||
#include <TFT_eSPI.h>
|
||||
#include "driver/ledc.h"
|
||||
#include <Adafruit_FT6206.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <memory>
|
||||
|
||||
/*LEDC Channel to use for the LCD backlight*/
|
||||
#define LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_5
|
||||
|
@ -16,58 +16,71 @@
|
|||
|
||||
#define DEFAULT_BACKLIGHT_BRIGHTNESS 128
|
||||
|
||||
class Display : public DisplayAbstract {
|
||||
public:
|
||||
static std::shared_ptr<Display> getInstance();
|
||||
|
||||
class Display: public DisplayAbstract
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<Display> getInstance();
|
||||
|
||||
/// @brief Set brightness setting and fade to it
|
||||
/// @param brightness
|
||||
virtual void setBrightness(uint8_t brightness) override;
|
||||
virtual uint8_t getBrightness() override;
|
||||
virtual void turnOff() override;
|
||||
|
||||
void onTouch(Notification<TS_Point>::HandlerTy aTouchHandler);
|
||||
/// @brief Set brightness setting and fade to it
|
||||
/// @param brightness
|
||||
virtual void setBrightness(uint8_t brightness) override;
|
||||
virtual uint8_t getBrightness() override;
|
||||
virtual void turnOff() override;
|
||||
|
||||
inline void wake() {if(isAsleep) {isAsleep = false; startFade();}}
|
||||
inline void sleep() {if(!isAsleep){isAsleep = true; startFade();}}
|
||||
std::shared_ptr<Notification<TS_Point>> TouchNotification() {
|
||||
return mTouchEvent;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
|
||||
virtual void screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) override;
|
||||
|
||||
/// @brief Fade toward brightness based on isAwake
|
||||
/// @return True - Fade complete
|
||||
/// False - Fade set point not reached
|
||||
bool fade();
|
||||
/// @brief Start the Fade task
|
||||
void startFade();
|
||||
inline void wake() {
|
||||
if (isAsleep) {
|
||||
isAsleep = false;
|
||||
startFade();
|
||||
}
|
||||
}
|
||||
inline void sleep() {
|
||||
if (!isAsleep) {
|
||||
isAsleep = true;
|
||||
startFade();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Set the actual display brightness right now
|
||||
/// @param brightness
|
||||
void setCurrentBrightness(uint8_t brightness);
|
||||
protected:
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p);
|
||||
virtual void screenInput(lv_indev_drv_t *indev_driver,
|
||||
lv_indev_data_t *data) override;
|
||||
|
||||
private:
|
||||
Display(int backlight_pin, int enable_pin);
|
||||
void setupTFT();
|
||||
void setupTouchScreen();
|
||||
void setupBacklight();
|
||||
|
||||
int mEnablePin;
|
||||
int mBacklightPin;
|
||||
TFT_eSPI tft;
|
||||
/// @brief Fade toward brightness based on isAwake
|
||||
/// @return True - Fade complete
|
||||
/// False - Fade set point not reached
|
||||
bool fade();
|
||||
/// @brief Start the Fade task
|
||||
void startFade();
|
||||
|
||||
Adafruit_FT6206 touch;
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
Notification<TS_Point> mTouchEvent;
|
||||
/// @brief Set the actual display brightness right now
|
||||
/// @param brightness
|
||||
void setCurrentBrightness(uint8_t brightness);
|
||||
|
||||
TaskHandle_t mDisplayFadeTask = nullptr;
|
||||
SemaphoreHandle_t mFadeTaskMutex = nullptr;
|
||||
static void fadeImpl(void* aBrightness);
|
||||
private:
|
||||
Display(int backlight_pin, int enable_pin);
|
||||
void setupTFT();
|
||||
void setupTouchScreen();
|
||||
void setupBacklight();
|
||||
|
||||
uint8_t mBrightness = 0; // Current display brightness
|
||||
uint8_t mAwakeBrightness = 100; // Current setting for brightness when awake
|
||||
bool isAsleep = false;
|
||||
int mEnablePin;
|
||||
int mBacklightPin;
|
||||
TFT_eSPI tft;
|
||||
|
||||
Adafruit_FT6206 touch;
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
std::shared_ptr<Notification<TS_Point>> mTouchEvent =
|
||||
std::make_shared<Notification<TS_Point>>();
|
||||
|
||||
TaskHandle_t mDisplayFadeTask = nullptr;
|
||||
SemaphoreHandle_t mFadeTaskMutex = nullptr;
|
||||
static void fadeImpl(void *aBrightness);
|
||||
|
||||
uint8_t mBrightness = 0; // Current display brightness
|
||||
uint8_t mAwakeBrightness = 100; // Current setting for brightness when awake
|
||||
bool isAsleep = false;
|
||||
};
|
61
Platformio/HAL/Targets/ESP32/keys/keys.cpp
Normal file
61
Platformio/HAL/Targets/ESP32/keys/keys.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "keys.hpp"
|
||||
|
||||
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) {
|
||||
BaseType_t higherPriorityTaskAwoke;
|
||||
xQueueSendFromISR(mKeyPressQueueHandle, &aJustOccuredKeyEvent,
|
||||
&higherPriorityTaskAwoke);
|
||||
};
|
||||
|
||||
void Keys::GrabKeys() {
|
||||
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 == RELEASED) {
|
||||
// May need to think about resetting sleep timer in key handler....
|
||||
// standbyTimer =
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
Platformio/HAL/Targets/ESP32/keys/keys.hpp
Normal file
76
Platformio/HAL/Targets/ESP32/keys/keys.hpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
#include "KeyPressAbstract.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include <Keypad.h> // modified for inverted logic
|
||||
#include <map>
|
||||
|
||||
class Keys : public KeyPressAbstract {
|
||||
public:
|
||||
Keys();
|
||||
void HandleKeyPresses() override;
|
||||
void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) override;
|
||||
|
||||
protected:
|
||||
void GrabKeys();
|
||||
|
||||
private:
|
||||
static void KeyGrabberTask(void *aSelf);
|
||||
static void KeyProccessor(void *aSelf);
|
||||
|
||||
QueueHandle_t mKeyPressQueueHandle;
|
||||
TaskHandle_t mKeyGrabbingTask;
|
||||
TaskHandle_t mKeyHandlingTask;
|
||||
|
||||
// Keypad declarations
|
||||
static const byte ROWS = 5; // four rows
|
||||
static const byte COLS = 5; // four columns
|
||||
// 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
|
||||
{'4', 'v', '1', '3', '2'}, // blue, channel-, red, yellow, green
|
||||
{'>', '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,
|
||||
SW_5}; // connect to the column pinouts of the keypad
|
||||
Keypad customKeypad =
|
||||
Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
|
||||
};
|
|
@ -45,8 +45,8 @@
|
|||
#define IR_VCC 25 // IR receiver power
|
||||
#define IR_LED 33 // IR LED output
|
||||
|
||||
#define SCL 22
|
||||
#define SDA 19
|
||||
#define TFT_SCL 22
|
||||
#define TFT_SDA 19
|
||||
#define ACC_INT 20
|
||||
|
||||
#define CRG_STAT 21 // battery charger feedback
|
|
@ -1,230 +1,116 @@
|
|||
#include "wifihandler.hpp"
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include <Arduino.h>
|
||||
#include <Preferences.h>
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "WiFi.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
std::shared_ptr<wifiHandler> wifiHandler::mInstance = nullptr;
|
||||
|
||||
// WiFi status event
|
||||
void wifiHandler::WiFiEvent(WiFiEvent_t event){
|
||||
int no_networks = 0;
|
||||
switch (event)
|
||||
{
|
||||
case ARDUINO_EVENT_WIFI_SCAN_DONE:
|
||||
{
|
||||
Serial.println("WIFI scan done\n");
|
||||
no_networks = WiFi.scanComplete();
|
||||
std::vector<WifiInfo> *vec = new std::vector<WifiInfo>();
|
||||
std::shared_ptr<std::vector<WifiInfo>> info = std::shared_ptr<std::vector<WifiInfo>>(vec);
|
||||
|
||||
for (int i = 0; i < no_networks; i++)
|
||||
{
|
||||
info->push_back(WifiInfo {
|
||||
.ssid = std::string(WiFi.SSID(i).c_str()),
|
||||
.rssi = WiFi.RSSI(i)
|
||||
});
|
||||
}
|
||||
if (no_networks < 0)
|
||||
{
|
||||
Serial.println("Scan failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Convert To callbacks
|
||||
//this->display.clear_wifi_networks();
|
||||
Serial.print(no_networks);
|
||||
Serial.print(" found\n");
|
||||
//this->display.wifi_scan_complete( no_networks);
|
||||
}
|
||||
this->scan_notification.notify(info);
|
||||
if (WiFi.isConnected() == false)
|
||||
{
|
||||
WiFi.reconnect();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
this->update_credentials();
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_STOP:
|
||||
this->update_status();
|
||||
default:
|
||||
Serial.print("Wifi Status: ");
|
||||
Serial.println(WiFi.status());
|
||||
break;
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECT_FAILED)
|
||||
{
|
||||
Serial.println("connection failed.");
|
||||
WiFi.disconnect();
|
||||
}
|
||||
Serial.println(WiFi.status());
|
||||
}
|
||||
|
||||
bool wifiHandler::isAvailable(){
|
||||
return true;
|
||||
}
|
||||
std::shared_ptr<wifiHandler> wifiHandler::getInstance()
|
||||
{
|
||||
if(mInstance)
|
||||
{
|
||||
return mInstance;
|
||||
}
|
||||
mInstance = std::shared_ptr<wifiHandler>(new wifiHandler());
|
||||
std::shared_ptr<wifiHandler> wifiHandler::getInstance() {
|
||||
if (mInstance) {
|
||||
return mInstance;
|
||||
}
|
||||
mInstance = std::shared_ptr<wifiHandler>(new wifiHandler());
|
||||
return mInstance;
|
||||
};
|
||||
|
||||
wifiHandler::wifiHandler()
|
||||
{
|
||||
this->password = "";
|
||||
this->SSID = "";
|
||||
}
|
||||
|
||||
void wifiHandler::update_status()
|
||||
{
|
||||
Serial.println("update_status");
|
||||
std::shared_ptr<wifiStatus> status = std::make_shared<wifiStatus>(wifiStatus());
|
||||
//wifiStatus *status = new wifiStatus();
|
||||
status->isConnected = WiFi.isConnected();
|
||||
//status->IP = WiFi.localIP();
|
||||
IPAddress ip = WiFi.localIP();
|
||||
String ip_str = ip.toString();
|
||||
status->IP = ip.toString().c_str();
|
||||
|
||||
//ip.copy(status->IP, ip.length());
|
||||
String ssid = WiFi.SSID();
|
||||
status->ssid = WiFi.SSID().c_str();
|
||||
|
||||
//this->wifi_status.isConnected = WiFi.isConnected();
|
||||
//this->wifi_status.IP = WiFi.localIP();
|
||||
//this->wifi_status.isConnected = true;
|
||||
|
||||
|
||||
//Serial.println(WiFi.localIP());
|
||||
this->status_update.notify(status);
|
||||
}
|
||||
|
||||
void wifiHandler::update_credentials()
|
||||
{
|
||||
// No connection was attempted so don't try to to save the creds
|
||||
if(!this->connect_attempt) return;
|
||||
#if 0
|
||||
if (strcmp(temporary_password, wifiHandler::password) != 0 || strcmp(temporary_ssid, wifiHandler::SSID) != 0)
|
||||
{
|
||||
strcpy(wifiHandler::password, temporary_password);
|
||||
strcpy(wifiHandler::SSID, temporary_ssid);
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifiSettings", false);
|
||||
String tempString = wifiHandler::password;
|
||||
preferences.putString("password", tempString);
|
||||
tempString = wifiHandler::SSID;
|
||||
preferences.putString("SSID", tempString);
|
||||
preferences.end();
|
||||
void wifiHandler::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t aEventInfo) {
|
||||
int no_networks = 0;
|
||||
switch (event) {
|
||||
case ARDUINO_EVENT_WIFI_SCAN_DONE: {
|
||||
no_networks = WiFi.scanComplete();
|
||||
auto info = std::vector<WifiInfo>(no_networks);
|
||||
for (int i = 0; i < no_networks; i++) {
|
||||
auto ssid =
|
||||
WiFi.SSID(i).c_str() ? std::string(WiFi.SSID(i).c_str()) : "No SSID";
|
||||
info[i] = WifiInfo(ssid, WiFi.RSSI(i));
|
||||
}
|
||||
#else
|
||||
if (this->temporary_password->compare(this->password) != 0 || this->temporary_ssid->compare(this->SSID))
|
||||
{
|
||||
this->password = *(this->temporary_password);
|
||||
this->SSID = *(this->temporary_ssid);
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifiSettings", false);
|
||||
String tempString = this->temporary_password->c_str();
|
||||
preferences.putString("password", tempString);
|
||||
tempString = this->temporary_ssid->c_str();
|
||||
preferences.putString("SSID", tempString);
|
||||
preferences.end();
|
||||
mScanNotification->notify(info);
|
||||
if (WiFi.isConnected() == false) {
|
||||
WiFi.reconnect();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
StoreCredentials();
|
||||
WiFi.setAutoConnect(true);
|
||||
UpdateStatus();
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_STOP:
|
||||
UpdateStatus();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
this->connect_attempt = false;
|
||||
}
|
||||
|
||||
void wifiHandler::scan()
|
||||
{
|
||||
void wifiHandler::UpdateStatus() {
|
||||
Serial.println("UpdateStatus");
|
||||
mCurrentStatus.isConnected = WiFi.isConnected();
|
||||
mCurrentStatus.IP = WiFi.localIP().toString().c_str();
|
||||
mCurrentStatus.ssid =
|
||||
mCurrentStatus.isConnected ? WiFi.SSID().c_str() : mConnectionAttemptSSID;
|
||||
|
||||
mStatusUpdate->notify(mCurrentStatus);
|
||||
}
|
||||
|
||||
void wifiHandler::StoreCredentials() {
|
||||
// No connection was attempted so don't try to to save the creds
|
||||
if (!mIsConnectionAttempt) {
|
||||
return;
|
||||
}
|
||||
mPassword = mConnectionAttemptPassword;
|
||||
mSSID = mConnectionAttemptSSID;
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifiSettings", false);
|
||||
preferences.putString("password", mPassword.c_str());
|
||||
preferences.putString("SSID", mSSID.c_str());
|
||||
preferences.end();
|
||||
|
||||
mConnectionAttemptPassword.clear();
|
||||
mConnectionAttemptSSID.clear();
|
||||
mIsConnectionAttempt = false;
|
||||
}
|
||||
|
||||
void wifiHandler::scan() {
|
||||
Serial.println("scan called");
|
||||
/* If the */
|
||||
WiFi.status();
|
||||
if (WiFi.isConnected() != true)
|
||||
{
|
||||
WiFi.setAutoReconnect(false);
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
|
||||
void wifiHandler::begin() {
|
||||
WiFi.setHostname("OMOTE");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t aEventInfo) {
|
||||
mInstance->WiFiEvent(event, aEventInfo);
|
||||
});
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifiSettings", false);
|
||||
String ssid = preferences.getString("SSID");
|
||||
String password = preferences.getString("password");
|
||||
preferences.end();
|
||||
|
||||
// Attempt Connection with stored Credentials
|
||||
if (!ssid.isEmpty()) {
|
||||
connect(ssid.c_str(), password.c_str());
|
||||
} else {
|
||||
Serial.println("no SSID or password stored");
|
||||
WiFi.disconnect();
|
||||
}
|
||||
WiFi.scanNetworks(true);
|
||||
|
||||
WiFi.setSleep(true);
|
||||
}
|
||||
|
||||
|
||||
void wifiHandler::begin()
|
||||
{
|
||||
//this->display = display;
|
||||
WiFi.setHostname("OMOTE");
|
||||
WiFi.mode(WIFI_STA);
|
||||
//WiFi.onEvent([this] (WiFiEvent_t event) {mInstance->WiFiEvent(event);});
|
||||
WiFi.onEvent([] (WiFiEvent_t event) {mInstance->WiFiEvent(event);});
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifiSettings",false);
|
||||
String ssid = preferences.getString("SSID");
|
||||
String password = preferences.getString("password");
|
||||
preferences.end();
|
||||
|
||||
/* If the SSID is not empty, there was a value stored in the preferences and we try to use it.*/
|
||||
if (!ssid.isEmpty())
|
||||
{
|
||||
Serial.print("Connecting to wifi ");
|
||||
Serial.println(ssid);
|
||||
//strcpy(this->SSID, ssid.c_str());
|
||||
//strcpy(this->password, password.c_str());
|
||||
this->SSID = ssid.c_str();
|
||||
this->password = password.c_str();
|
||||
this->connect(std::make_shared<std::string>(std::string(this->SSID)), std::make_shared<std::string>(std::string(this->password)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("no SSID or password stored");
|
||||
/*Set first character to \0 indicates an empty string*/
|
||||
this->SSID[0] = '\0';
|
||||
this->password[0] = '\0';
|
||||
WiFi.disconnect();
|
||||
}
|
||||
|
||||
WiFi.setSleep(true);
|
||||
void wifiHandler::connect(std::string ssid, std::string password) {
|
||||
Serial.printf("Attempting Wifi Connection To %s \n", ssid.c_str());
|
||||
mIsConnectionAttempt = true;
|
||||
mConnectionAttemptPassword = password;
|
||||
mConnectionAttemptSSID = ssid;
|
||||
auto status = WiFi.begin(mConnectionAttemptSSID.c_str(),
|
||||
mConnectionAttemptPassword.c_str());
|
||||
}
|
||||
|
||||
void wifiHandler::onScanDone(std::function<void (std::shared_ptr<std::vector<WifiInfo>>)> function){
|
||||
this->scan_notification.onNotify(std::move(function));
|
||||
}
|
||||
|
||||
void wifiHandler::onStatusUpdate(std::function<void (std::shared_ptr<wifiStatus>)> function){
|
||||
this->status_update.onNotify(std::move(function));
|
||||
}
|
||||
|
||||
void wifiHandler::connect(std::shared_ptr<std::string> ssid, std::shared_ptr<std::string> password)
|
||||
{
|
||||
this->connect_attempt = true;
|
||||
this->temporary_password = password;
|
||||
this->temporary_ssid = ssid;
|
||||
WiFi.begin(ssid->c_str(), password->c_str());
|
||||
}
|
||||
|
||||
void wifiHandler::turnOff()
|
||||
{
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
|
||||
void wifiHandler::disconnect(){
|
||||
WiFi.disconnect();
|
||||
}
|
||||
|
||||
bool wifiHandler::isConnected()
|
||||
{
|
||||
return WiFi.isConnected();
|
||||
}
|
||||
|
||||
std::string wifiHandler::getIP()
|
||||
{
|
||||
return std::string(WiFi.localIP().toString().c_str());
|
||||
}
|
|
@ -1,99 +1,53 @@
|
|||
#pragma once
|
||||
#include "wifiHandlerInterface.h"
|
||||
#include "Notification.hpp"
|
||||
#include "memory.h"
|
||||
#include "wifiHandlerInterface.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#define STRING_SIZE 50
|
||||
class wifiHandler : public wifiHandlerInterface {
|
||||
public:
|
||||
static std::shared_ptr<wifiHandler> getInstance();
|
||||
|
||||
class wifiHandler: public wifiHandlerInterface {
|
||||
public:
|
||||
wifiHandler();
|
||||
static std::shared_ptr<wifiHandler> getInstance();
|
||||
/**
|
||||
* @brief Function to initialize the wifi handler
|
||||
*
|
||||
*/
|
||||
void begin();
|
||||
// wifiHandlerInterface Implementation
|
||||
void begin() override;
|
||||
void scan() override;
|
||||
void connect(std::string ssid, std::string password) override;
|
||||
wifiStatus GetStatus() override { return mCurrentStatus; };
|
||||
//
|
||||
|
||||
/**
|
||||
* @brief Connect to the wifi using the provided credetials
|
||||
*
|
||||
* @param SSID
|
||||
* @param password
|
||||
*/
|
||||
void connect(std::shared_ptr<std::string> ssid, std::shared_ptr<std::string> password);
|
||||
//void connect(const char* SSID, const char* password);
|
||||
protected:
|
||||
wifiHandler() = default;
|
||||
static std::shared_ptr<wifiHandler> mInstance;
|
||||
|
||||
/**
|
||||
* @brief Function to store the credentials when we have had a
|
||||
* successful connection
|
||||
*/
|
||||
void StoreCredentials();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Handler for incoming arduino wifi events
|
||||
* @param event - a Wifi event
|
||||
*/
|
||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t aEventInfo);
|
||||
|
||||
/**
|
||||
* @brief function to trigger asynchronous scan for wifi networks
|
||||
*
|
||||
*/
|
||||
void scan();
|
||||
bool isAvailable();
|
||||
void onScanDone(std::function<void (std::shared_ptr<std::vector<WifiInfo>>)> function);
|
||||
void onStatusUpdate(std::function<void (std::shared_ptr<wifiStatus>)> function);
|
||||
/**
|
||||
* @brief Update Internal status and send out a notification
|
||||
*/
|
||||
void UpdateStatus();
|
||||
wifiStatus mCurrentStatus;
|
||||
|
||||
/**
|
||||
* @brief Variables used to track wifi connection attempts
|
||||
*/
|
||||
bool mIsConnectionAttempt = false;
|
||||
std::string mConnectionAttemptPassword;
|
||||
std::string mConnectionAttemptSSID;
|
||||
|
||||
private:
|
||||
|
||||
Notification<std::shared_ptr<std::vector<WifiInfo>>> scan_notification;
|
||||
Notification<std::shared_ptr<wifiStatus>> status_update;
|
||||
/**
|
||||
* @brief Function to update the wifi credentials. This function is called in the wifi event callback function
|
||||
* after a connection is established. Only then is the new credentials stored and the old stored credentials
|
||||
* overwritten.
|
||||
*
|
||||
* @param temporary_ssid
|
||||
* @param temporary_password
|
||||
*/
|
||||
void update_credentials();
|
||||
|
||||
void WiFiEvent(WiFiEvent_t event);
|
||||
|
||||
/**
|
||||
* @brief Function to turn off wifi
|
||||
*
|
||||
*/
|
||||
void turnOff();
|
||||
/**
|
||||
* @brief Function to get the IP address of this device
|
||||
*
|
||||
* @return String IP Address of the device
|
||||
*/
|
||||
std::string getIP();
|
||||
wifiStatus wifi_status;
|
||||
static std::shared_ptr<wifiHandler> mInstance;
|
||||
bool connect_attempt = false;
|
||||
std::shared_ptr<std::string> temporary_password;
|
||||
std::shared_ptr<std::string> temporary_ssid;
|
||||
|
||||
void update_status();
|
||||
/**
|
||||
* @brief Internal variable to store the wifi password
|
||||
*
|
||||
*/
|
||||
std::string password;
|
||||
|
||||
/**
|
||||
* @brief Function to disconnect from the network
|
||||
*
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* @brief Function to determine wether or not we are connected to a network
|
||||
*
|
||||
* @return true Device is connected to wifi network
|
||||
* @return false Device is not connected to wifi network
|
||||
*/
|
||||
bool isConnected();
|
||||
/**
|
||||
* @brief Internal variable to store the wifi SSID
|
||||
*
|
||||
*/
|
||||
std::string SSID;
|
||||
|
||||
/**
|
||||
* @brief Verified Working User and Pass to Wifi network
|
||||
*/
|
||||
std::string mPassword;
|
||||
std::string mSSID;
|
||||
};
|
|
@ -3,70 +3,60 @@
|
|||
#include "SDLDisplay.hpp"
|
||||
#include <sstream>
|
||||
|
||||
HardwareSimulator::HardwareSimulator(): HardwareAbstract(),
|
||||
mTickThread([](){
|
||||
while(true){
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/
|
||||
}}),
|
||||
mBattery(std::make_shared<BatterySimulator>()),
|
||||
mDisplay(SDLDisplay::getInstance()),
|
||||
mWifiHandler(std::make_shared<wifiHandlerSim>())
|
||||
{
|
||||
mHardwareStatusTitleUpdate = std::thread([this] {
|
||||
int dataToShow = 0;
|
||||
while (true)
|
||||
{
|
||||
std::stringstream title;
|
||||
switch (dataToShow){
|
||||
case 0:
|
||||
title << "Batt:" << mBattery->getPercentage() << "%" << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
title << "BKLght: " << static_cast<int>(mDisplay->getBrightness()) << std::endl;
|
||||
dataToShow = -1;
|
||||
break;
|
||||
default:
|
||||
dataToShow = -1;
|
||||
}
|
||||
dataToShow++;
|
||||
|
||||
mDisplay->setTitle(title.str());
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
HardwareSimulator::HardwareSimulator()
|
||||
: HardwareAbstract(), mTickThread([]() {
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/
|
||||
}
|
||||
});
|
||||
}),
|
||||
mBattery(std::make_shared<BatterySimulator>()),
|
||||
mDisplay(SDLDisplay::getInstance()),
|
||||
mWifiHandler(std::make_shared<wifiHandlerSim>()),
|
||||
mKeys(std::make_shared<KeyPressSim>()) {
|
||||
mHardwareStatusTitleUpdate = std::thread([this] {
|
||||
int dataToShow = 0;
|
||||
while (true) {
|
||||
std::stringstream title;
|
||||
switch (dataToShow) {
|
||||
case 0:
|
||||
title << "Batt:" << mBattery->getPercentage() << "%" << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
title << "BKLght: " << static_cast<int>(mDisplay->getBrightness())
|
||||
<< std::endl;
|
||||
dataToShow = -1;
|
||||
break;
|
||||
default:
|
||||
dataToShow = -1;
|
||||
}
|
||||
dataToShow++;
|
||||
|
||||
mDisplay->setTitle(title.str());
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<BatteryInterface> HardwareSimulator::battery(){
|
||||
return mBattery;
|
||||
std::shared_ptr<BatteryInterface> HardwareSimulator::battery() {
|
||||
return mBattery;
|
||||
}
|
||||
std::shared_ptr<DisplayAbstract> HardwareSimulator::display(){
|
||||
return mDisplay;
|
||||
std::shared_ptr<DisplayAbstract> HardwareSimulator::display() {
|
||||
return mDisplay;
|
||||
}
|
||||
std::shared_ptr<wifiHandlerInterface> HardwareSimulator::wifi(){
|
||||
return mWifiHandler;
|
||||
std::shared_ptr<wifiHandlerInterface> HardwareSimulator::wifi() {
|
||||
return mWifiHandler;
|
||||
}
|
||||
std::shared_ptr<KeyPressAbstract> HardwareSimulator::keys() { return mKeys; }
|
||||
|
||||
char HardwareSimulator::getCurrentDevice(){
|
||||
return 0;
|
||||
}
|
||||
char HardwareSimulator::getCurrentDevice() { return 0; }
|
||||
|
||||
void HardwareSimulator::setCurrentDevice(char currentDevice){
|
||||
void HardwareSimulator::setCurrentDevice(char currentDevice) {}
|
||||
|
||||
}
|
||||
bool HardwareSimulator::getWakeupByIMUEnabled() { return true; }
|
||||
|
||||
bool HardwareSimulator::getWakeupByIMUEnabled(){
|
||||
return true;
|
||||
}
|
||||
void HardwareSimulator::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) {}
|
||||
|
||||
void HardwareSimulator::setWakeupByIMUEnabled(bool wakeupByIMUEnabled){
|
||||
uint16_t HardwareSimulator::getSleepTimeout() { return 20000; }
|
||||
|
||||
}
|
||||
|
||||
uint16_t HardwareSimulator::getSleepTimeout(){
|
||||
return 20000;
|
||||
}
|
||||
|
||||
void HardwareSimulator::setSleepTimeout(uint16_t sleepTimeout){
|
||||
|
||||
}
|
||||
void HardwareSimulator::setSleepTimeout(uint16_t sleepTimeout) {}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
#include "HardwareAbstract.hpp"
|
||||
|
||||
#include "batterySimulator.hpp"
|
||||
#include "KeyPressSim.hpp"
|
||||
#include "SDLDisplay.hpp"
|
||||
#include "batterySimulator.hpp"
|
||||
#include "wifiHandlerSim.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
@ -10,28 +11,30 @@
|
|||
class HardwareSimulator : public HardwareAbstract {
|
||||
public:
|
||||
HardwareSimulator();
|
||||
|
||||
virtual void init() override {};
|
||||
|
||||
virtual void debugPrint(const char* fmt, ...) override {
|
||||
void init() override{};
|
||||
void loopHandler() override{};
|
||||
|
||||
void debugPrint(const char *fmt, ...) override {
|
||||
va_list arguments;
|
||||
va_start(arguments, fmt);
|
||||
vprintf(fmt, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<BatteryInterface> battery() override;
|
||||
virtual std::shared_ptr<DisplayAbstract> display() override;
|
||||
virtual std::shared_ptr<wifiHandlerInterface> wifi() override;
|
||||
std::shared_ptr<BatteryInterface> battery() override;
|
||||
std::shared_ptr<DisplayAbstract> display() override;
|
||||
std::shared_ptr<wifiHandlerInterface> wifi() override;
|
||||
std::shared_ptr<KeyPressAbstract> keys() override;
|
||||
|
||||
virtual char getCurrentDevice() override;
|
||||
virtual void setCurrentDevice(char currentDevice) override;
|
||||
char getCurrentDevice() override;
|
||||
void setCurrentDevice(char currentDevice) override;
|
||||
|
||||
virtual bool getWakeupByIMUEnabled() override;
|
||||
virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override;
|
||||
bool getWakeupByIMUEnabled() override;
|
||||
void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override;
|
||||
|
||||
virtual uint16_t getSleepTimeout() override;
|
||||
virtual void setSleepTimeout(uint16_t sleepTimeout) override;
|
||||
uint16_t getSleepTimeout() override;
|
||||
void setSleepTimeout(uint16_t sleepTimeout) override;
|
||||
|
||||
private:
|
||||
std::thread mTickThread;
|
||||
|
@ -40,4 +43,5 @@ private:
|
|||
std::shared_ptr<BatterySimulator> mBattery;
|
||||
std::shared_ptr<SDLDisplay> mDisplay;
|
||||
std::shared_ptr<wifiHandlerSim> mWifiHandler;
|
||||
std::shared_ptr<KeyPressSim> mKeys;
|
||||
};
|
||||
|
|
44
Platformio/HAL/Targets/Simulator/KeyPressSim.cpp
Normal file
44
Platformio/HAL/Targets/Simulator/KeyPressSim.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "KeyPressSim.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
KeyPressSim::KeyPressSim()
|
||||
: mKeyHandlerThread([this] {
|
||||
while (true) {
|
||||
HandleKeyPresses();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
}) {
|
||||
SDL_AddEventWatch(KeyPressSim::GrabKeyImpl, this);
|
||||
};
|
||||
|
||||
int KeyPressSim::GrabKeyImpl(void *aSelf, SDL_Event *aEvent) {
|
||||
reinterpret_cast<KeyPressSim *>(aSelf)->GrabKeys(aEvent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KeyPressSim::GrabKeys(SDL_Event *aEvent) {
|
||||
if (aEvent->type == SDL_KEYDOWN || aEvent->type == SDL_KEYUP) {
|
||||
auto keyEventType = aEvent->type == SDL_KEYDOWN ? KeyEvent::Type::Press
|
||||
: KeyEvent::Type::Release;
|
||||
const auto SDLK_key = aEvent->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()) {
|
||||
if (mKeyEventHandler) {
|
||||
mKeyEventHandler(mKeyEventQueue.front());
|
||||
}
|
||||
mKeyEventQueue.pop();
|
||||
}
|
||||
};
|
||||
|
||||
void KeyPressSim::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) {
|
||||
std::lock_guard lock(mQueueGaurd);
|
||||
mKeyEventQueue.push(aJustOccuredKeyEvent);
|
||||
};
|
59
Platformio/HAL/Targets/Simulator/KeyPressSim.hpp
Normal file
59
Platformio/HAL/Targets/Simulator/KeyPressSim.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#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();
|
||||
|
||||
static int GrabKeyImpl(void *aSelf, SDL_Event *aEvent);
|
||||
void GrabKeys(SDL_Event *aEvent);
|
||||
|
||||
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}};
|
||||
};
|
|
@ -1,39 +1,39 @@
|
|||
#include "SDLDisplay.hpp"
|
||||
#include "sdl/sdl.h"
|
||||
#include <string>
|
||||
#include <string>
|
||||
|
||||
std::shared_ptr<SDLDisplay> SDLDisplay::getInstance(){
|
||||
if (!DisplayAbstract::mInstance){
|
||||
DisplayAbstract::mInstance = std::shared_ptr<SDLDisplay>(new SDLDisplay());
|
||||
}
|
||||
return std::static_pointer_cast<SDLDisplay>(mInstance);
|
||||
std::shared_ptr<SDLDisplay> SDLDisplay::getInstance() {
|
||||
if (!DisplayAbstract::mInstance) {
|
||||
DisplayAbstract::mInstance = std::shared_ptr<SDLDisplay>(new SDLDisplay());
|
||||
}
|
||||
return std::static_pointer_cast<SDLDisplay>(mInstance);
|
||||
}
|
||||
|
||||
void SDLDisplay::setBrightness(uint8_t brightness){
|
||||
mBrightness = brightness;
|
||||
void SDLDisplay::setBrightness(uint8_t brightness) { mBrightness = brightness; }
|
||||
|
||||
uint8_t SDLDisplay::getBrightness() { return mBrightness; }
|
||||
|
||||
void SDLDisplay::turnOff() {}
|
||||
|
||||
void SDLDisplay::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p) {
|
||||
sdl_display_flush(disp, area, color_p);
|
||||
}
|
||||
|
||||
uint8_t SDLDisplay::getBrightness(){
|
||||
return mBrightness;
|
||||
void SDLDisplay::screenInput(lv_indev_drv_t *indev_driver,
|
||||
lv_indev_data_t *data) {
|
||||
sdl_mouse_read(indev_driver, data);
|
||||
}
|
||||
|
||||
void SDLDisplay::turnOff(){
|
||||
|
||||
void SDLDisplay::setTitle(std::string aNewTitle) {
|
||||
SDL_SetWindowTitle(mSimWindow, aNewTitle.c_str());
|
||||
}
|
||||
|
||||
void SDLDisplay::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p){
|
||||
sdl_display_flush(disp,area,color_p);
|
||||
}
|
||||
SDLDisplay::SDLDisplay() : DisplayAbstract() {
|
||||
sdl_init();
|
||||
|
||||
void SDLDisplay::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){
|
||||
sdl_mouse_read(indev_driver,data);
|
||||
}
|
||||
|
||||
void SDLDisplay::setTitle(std::string aNewTitle){
|
||||
SDL_SetWindowTitle(mSimWindow,aNewTitle.c_str());
|
||||
}
|
||||
|
||||
SDLDisplay::SDLDisplay(): DisplayAbstract() {
|
||||
sdl_init();
|
||||
mSimWindow = SDL_GetWindowFromID(1); // Get the SDL window via ID hopefully it is always 1...
|
||||
// Get the SDL window via an event
|
||||
SDL_Event aWindowIdFinder;
|
||||
SDL_PollEvent(&aWindowIdFinder);
|
||||
mSimWindow = SDL_GetWindowFromID(aWindowIdFinder.window.windowID);
|
||||
}
|
|
@ -1,25 +1,27 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "SDL2/SDL.h"
|
||||
#include "DisplayAbstract.h"
|
||||
#include "SDL2/SDL.h"
|
||||
#include <stdint.h>
|
||||
|
||||
class SDLDisplay : public DisplayAbstract{
|
||||
class SDLDisplay : public DisplayAbstract {
|
||||
|
||||
public:
|
||||
static std::shared_ptr<SDLDisplay> getInstance();
|
||||
static std::shared_ptr<SDLDisplay> getInstance();
|
||||
|
||||
virtual void setBrightness(uint8_t brightness) override;
|
||||
virtual uint8_t getBrightness() override;
|
||||
virtual void turnOff() override;
|
||||
virtual void setBrightness(uint8_t brightness) override;
|
||||
virtual uint8_t getBrightness() override;
|
||||
virtual void turnOff() override;
|
||||
|
||||
void setTitle(std::string aNewTitle);
|
||||
void setTitle(std::string aNewTitle);
|
||||
|
||||
protected:
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) override;
|
||||
virtual void screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) override;
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p) override;
|
||||
virtual void screenInput(lv_indev_drv_t *indev_driver,
|
||||
lv_indev_data_t *data) override;
|
||||
|
||||
private:
|
||||
SDLDisplay();
|
||||
uint8_t mBrightness;
|
||||
SDL_Window* mSimWindow;
|
||||
SDLDisplay();
|
||||
uint8_t mBrightness;
|
||||
SDL_Window *mSimWindow;
|
||||
};
|
|
@ -4,7 +4,7 @@ template <typename T>
|
|||
SimulatorSPSCQueue<T>::SimulatorSPSCQueue(uint32_t size)
|
||||
{
|
||||
this->size = size;
|
||||
this->data = new T[](this->size + 1);
|
||||
this->data = new T[this->size + 1];
|
||||
this->rd_index = 0;
|
||||
this->wr_index = 0;
|
||||
}
|
||||
|
|
|
@ -1,68 +1,35 @@
|
|||
#include "wifiHandlerSim.hpp"
|
||||
|
||||
std::shared_ptr<wifiHandlerSim> mInstance;
|
||||
using WifiInfo = wifiHandlerInterface::WifiInfo;
|
||||
|
||||
std::shared_ptr<wifiHandlerSim> wifiHandlerSim::getInstance()
|
||||
{
|
||||
if(mInstance)
|
||||
{
|
||||
return mInstance;
|
||||
}
|
||||
mInstance = std::make_shared<wifiHandlerSim>(wifiHandlerSim());
|
||||
return mInstance;
|
||||
};
|
||||
wifiHandlerSim::wifiHandlerSim() {}
|
||||
|
||||
wifiHandlerSim::wifiHandlerSim(){
|
||||
void wifiHandlerSim::begin() {}
|
||||
|
||||
}
|
||||
|
||||
void wifiHandlerSim::begin(){
|
||||
|
||||
}
|
||||
|
||||
static wifiStatus status = {
|
||||
.isConnected = true
|
||||
, .IP = "172.0.0.1"
|
||||
};
|
||||
|
||||
void wifiHandlerSim::connect(std::shared_ptr<std::string> ssid, std::shared_ptr<std::string> password){
|
||||
status.ssid = *ssid;
|
||||
std::shared_ptr<wifiStatus> new_status = std::make_shared<wifiStatus> (wifiStatus(std::move(status)));
|
||||
this->status_update.notify(new_status);
|
||||
void wifiHandlerSim::connect(std::string ssid, std::string password) {
|
||||
if (mFakeStatusThread.joinable()) {
|
||||
mFakeStatusThread.join();
|
||||
mCurrentStatus.ssid = ssid;
|
||||
mCurrentStatus.isConnected = true;
|
||||
mFakeStatusThread = std::thread([this] {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
mStatusUpdate->notify(mCurrentStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static const WifiInfo wifis[] = {
|
||||
{
|
||||
.ssid = "High Signal Wifi"
|
||||
, .rssi = -49
|
||||
}
|
||||
, {
|
||||
.ssid = "Mid Signal Wifi"
|
||||
, .rssi = -55
|
||||
}
|
||||
, {
|
||||
.ssid = "Low Signal Wifi"
|
||||
, .rssi = -65
|
||||
}
|
||||
, {
|
||||
.ssid = "No Signal Wifi"
|
||||
, .rssi = -90
|
||||
}
|
||||
};
|
||||
WifiInfo("High Signal Wifi", -49), WifiInfo("Mid Signal Wifi", -55),
|
||||
WifiInfo("Low Signal Wifi", -65), WifiInfo("No Signal Wifi", -90)};
|
||||
|
||||
void wifiHandlerSim::scan(){
|
||||
std::shared_ptr<std::vector<WifiInfo>> info = std::make_shared<std::vector<WifiInfo>>(std::vector(std::begin(wifis), std::end(wifis)));
|
||||
this->scan_notification.notify(info);
|
||||
void wifiHandlerSim::scan() {
|
||||
if (mFakeScanThread.joinable()) {
|
||||
mFakeScanThread.join();
|
||||
mFakeScanThread = std::thread([this] {
|
||||
std::vector<WifiInfo> info =
|
||||
std::vector(std::begin(wifis), std::end(wifis));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
mScanNotification->notify(info);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool wifiHandlerSim::isAvailable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
void wifiHandlerSim::onScanDone(std::function<void (std::shared_ptr<std::vector<WifiInfo>>)> function){
|
||||
this->scan_notification.onNotify(std::move(function));
|
||||
}
|
||||
|
||||
void wifiHandlerSim::onStatusUpdate(std::function<void (std::shared_ptr<wifiStatus>)> function){
|
||||
this->status_update.onNotify(std::move(function));
|
||||
}
|
|
@ -1,35 +1,21 @@
|
|||
#pragma once
|
||||
#include "wifiHandlerInterface.h"
|
||||
#include "Notification.hpp"
|
||||
#include "wifiHandlerInterface.h"
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
class wifiHandlerSim: public wifiHandlerInterface {
|
||||
public:
|
||||
wifiHandlerSim();
|
||||
static std::shared_ptr<wifiHandlerSim> getInstance();
|
||||
class wifiHandlerSim : public wifiHandlerInterface {
|
||||
public:
|
||||
wifiHandlerSim();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect to the wifi using the provided credetials
|
||||
*
|
||||
* @param SSID
|
||||
* @param password
|
||||
*/
|
||||
void connect(std::shared_ptr<std::string> ssid, std::shared_ptr<std::string> password);
|
||||
//void connect(const char* SSID, const char* password);
|
||||
void begin() override;
|
||||
void scan() override;
|
||||
void connect(std::string ssid, std::string password) override;
|
||||
wifiStatus GetStatus() override { return mCurrentStatus; };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief function to trigger asynchronous scan for wifi networks
|
||||
*
|
||||
*/
|
||||
void scan();
|
||||
bool isAvailable();
|
||||
void begin();
|
||||
void onScanDone(std::function<void (std::shared_ptr<std::vector<WifiInfo>>)> function);
|
||||
void onStatusUpdate(std::function<void (std::shared_ptr<wifiStatus>)> function);
|
||||
private:
|
||||
Notification<std::shared_ptr<std::vector<WifiInfo>>> scan_notification;
|
||||
Notification<std::shared_ptr<wifiStatus>> status_update;
|
||||
private:
|
||||
std::thread mFakeScanThread = std::thread([] {});
|
||||
std::thread mFakeStatusThread = std::thread([] {});
|
||||
wifiStatus mCurrentStatus = wifiStatus(true, "172.0.0.1", "FakeNet");
|
||||
};
|
File diff suppressed because it is too large
Load diff
|
@ -1,50 +0,0 @@
|
|||
// OMOTE UI Images
|
||||
// 2023 Matthew Colvin
|
||||
#pragma once
|
||||
#include "lvgl.h"
|
||||
|
||||
class Images{
|
||||
|
||||
public:
|
||||
Images();
|
||||
|
||||
lv_obj_t* addAppleTVIcon(lv_obj_t* parent);
|
||||
lv_obj_t* addAppleDisplayImage(lv_obj_t* parent);
|
||||
lv_obj_t* addAppleBackIcon(lv_obj_t* parent);
|
||||
|
||||
lv_obj_t* addLowBrightnessIcon(lv_obj_t* parent);
|
||||
lv_obj_t* addHighBrightnessIcon(lv_obj_t* parent);
|
||||
lv_obj_t* addLightBulbIcon(lv_obj_t* parent);
|
||||
|
||||
lv_obj_t* addLeftGradiant(lv_obj_t* parent);
|
||||
lv_obj_t* addRightGradiant(lv_obj_t* parent);
|
||||
|
||||
lv_obj_t* addWifiNoSignal(lv_obj_t* parent);
|
||||
lv_obj_t* addWifiLowSignal(lv_obj_t* parent);
|
||||
lv_obj_t* addWifiMidSignal(lv_obj_t* parent);
|
||||
lv_obj_t* addWifiHighSignal(lv_obj_t* parent);
|
||||
|
||||
|
||||
private:
|
||||
// Make Image based on anImageDesc then
|
||||
// add that image to parent.
|
||||
lv_obj_t* addImg(lv_obj_t* parent, lv_img_dsc_t* anImgDesc);
|
||||
void setupImageDescriptions();
|
||||
|
||||
lv_img_dsc_t appleTvIcon;
|
||||
lv_img_dsc_t appleDisplayIcon;
|
||||
lv_img_dsc_t appleBackIcon;
|
||||
|
||||
lv_img_dsc_t low_brightness;
|
||||
lv_img_dsc_t high_brightness;
|
||||
lv_img_dsc_t lightbulb_icon;
|
||||
|
||||
lv_img_dsc_t gradientLeft;
|
||||
lv_img_dsc_t gradientRight;
|
||||
|
||||
lv_img_dsc_t wifiNoSignal;
|
||||
lv_img_dsc_t wifiLowSignal;
|
||||
lv_img_dsc_t wifiMidSignal;
|
||||
lv_img_dsc_t wifiHighSignal;
|
||||
|
||||
};
|
|
@ -3,13 +3,16 @@
|
|||
#include "omoteconfig.h"
|
||||
#include <functional>
|
||||
|
||||
using namespace UI::Basic;
|
||||
|
||||
std::shared_ptr<OmoteUI> OmoteUI::mInstance = nullptr;
|
||||
|
||||
// This can be used to flag out specific code for SIM only
|
||||
// #if defined(IS_SIMULATOR) && (IS_SIMULATOR == true)
|
||||
// #endif
|
||||
|
||||
OmoteUI::OmoteUI(std::shared_ptr<HardwareAbstract> aHardware) : mHardware(aHardware){}
|
||||
OmoteUI::OmoteUI(std::shared_ptr<HardwareAbstract> aHardware)
|
||||
: UIBase(aHardware) {}
|
||||
|
||||
// Set the page indicator scroll position relative to the tabview scroll
|
||||
// position
|
||||
|
@ -37,17 +40,18 @@ void OmoteUI::bl_slider_event_cb(lv_event_t *e) {
|
|||
// Apple Key Event handler
|
||||
void OmoteUI::appleKey_event_cb(lv_event_t *e) {
|
||||
// Send IR command based on the event user data
|
||||
//mHardware->debugPrint(std::to_string(50 + (int)e->user_data));
|
||||
// mHardware->debugPrint(std::to_string(50 + (int)e->user_data));
|
||||
}
|
||||
|
||||
// Wakeup by IMU Switch Event handler
|
||||
void OmoteUI::WakeEnableSetting_event_cb(lv_event_t *e) {
|
||||
this->mHardware->setWakeupByIMUEnabled(lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
this->mHardware->setWakeupByIMUEnabled(
|
||||
lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
}
|
||||
|
||||
// Wakeup timeout dropdown Event handler
|
||||
void OmoteUI::wakeTimeoutSetting_event_cb(lv_event_t *e){
|
||||
lv_obj_t * drop = lv_event_get_target(e);
|
||||
void OmoteUI::wakeTimeoutSetting_event_cb(lv_event_t *e) {
|
||||
lv_obj_t *drop = lv_event_get_target(e);
|
||||
|
||||
int sleepTimeout = sleepTimeoutMap[lv_dropdown_get_selected(drop)];
|
||||
mHardware->setSleepTimeout(sleepTimeout);
|
||||
|
@ -97,13 +101,14 @@ void OmoteUI::virtualKeypad_event_cb(lv_event_t *e) {
|
|||
// mHardware->debugPrint(buffer);
|
||||
}
|
||||
|
||||
void OmoteUI::loopHandler(){
|
||||
void OmoteUI::loopHandler() {
|
||||
lv_timer_handler();
|
||||
lv_task_handler();
|
||||
}
|
||||
|
||||
void OmoteUI::create_status_bar(){
|
||||
void OmoteUI::create_status_bar() {
|
||||
// Create a status bar
|
||||
lv_obj_t* statusbar = lv_btn_create(lv_scr_act());
|
||||
lv_obj_t *statusbar = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(statusbar, 240, 20);
|
||||
lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN);
|
||||
|
@ -113,32 +118,41 @@ void OmoteUI::create_status_bar(){
|
|||
this->WifiLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->WifiLabel, "");
|
||||
lv_obj_align(this->WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
|
||||
lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12,
|
||||
LV_PART_MAIN);
|
||||
|
||||
this->objBattPercentage = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->objBattPercentage, "");
|
||||
lv_obj_align(this->objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
|
||||
lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12,
|
||||
LV_PART_MAIN);
|
||||
|
||||
this->objBattIcon = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
lv_obj_align(this->objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
|
||||
lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16,
|
||||
LV_PART_MAIN);
|
||||
|
||||
batteryPoller = std::make_unique<poller>([&batteryIcon = objBattIcon, battery = mHardware->battery()](){
|
||||
auto percent = battery->getPercentage();
|
||||
if(percent > 95) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL);
|
||||
else if(percent > 75) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3);
|
||||
else if(percent > 50) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2);
|
||||
else if(percent > 25) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1);
|
||||
else lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
});
|
||||
batteryPoller = std::make_unique<poller>(
|
||||
[&batteryIcon = objBattIcon, battery = mHardware->battery()]() {
|
||||
auto percent = battery->getPercentage();
|
||||
if (percent > 95)
|
||||
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL);
|
||||
else if (percent > 75)
|
||||
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3);
|
||||
else if (percent > 50)
|
||||
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2);
|
||||
else if (percent > 25)
|
||||
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1);
|
||||
else
|
||||
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
});
|
||||
}
|
||||
|
||||
void OmoteUI::setup_settings(lv_obj_t* parent)
|
||||
{
|
||||
void OmoteUI::setup_settings(lv_obj_t *parent) {
|
||||
// Add content to the settings tab
|
||||
// With a flex layout, setting groups/boxes will position themselves automatically
|
||||
// With a flex layout, setting groups/boxes will position themselves
|
||||
// automatically
|
||||
lv_obj_set_layout(parent, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
@ -148,19 +162,19 @@ void OmoteUI::setup_settings(lv_obj_t* parent)
|
|||
|
||||
/* Create main page for settings this->settingsMenu*/
|
||||
this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL);
|
||||
lv_obj_t* cont = lv_menu_cont_create(this->settingsMainPage);
|
||||
lv_obj_t *cont = lv_menu_cont_create(this->settingsMainPage);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
//lv_obj_set_width(cont, lv_obj_get_width(parent));
|
||||
// lv_obj_set_width(cont, lv_obj_get_width(parent));
|
||||
this->display_settings(cont);
|
||||
|
||||
this->create_wifi_settings(this->settingsMenu, cont);
|
||||
|
||||
// Another setting for the battery
|
||||
lv_obj_t* menuLabel = lv_label_create(cont);
|
||||
lv_obj_t *menuLabel = lv_label_create(cont);
|
||||
lv_label_set_text(menuLabel, "Battery");
|
||||
lv_obj_t* menuBox = lv_obj_create(cont);
|
||||
lv_obj_t *menuBox = lv_obj_create(cont);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 125);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
@ -168,79 +182,81 @@ void OmoteUI::setup_settings(lv_obj_t* parent)
|
|||
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
|
||||
}
|
||||
|
||||
void OmoteUI::ta_kb_event_cb(lv_event_t* e)
|
||||
{
|
||||
void OmoteUI::ta_kb_event_cb(lv_event_t *e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * ta = lv_event_get_target(e);
|
||||
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e);
|
||||
switch(code){
|
||||
case LV_EVENT_FOCUSED:
|
||||
lv_keyboard_set_textarea(kb, ta);
|
||||
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(kb);
|
||||
break;
|
||||
case LV_EVENT_DEFOCUSED:
|
||||
lv_keyboard_set_textarea(kb, NULL);
|
||||
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
lv_obj_t *ta = lv_event_get_target(e);
|
||||
lv_obj_t *kb = (lv_obj_t *)lv_event_get_user_data(e);
|
||||
switch (code) {
|
||||
case LV_EVENT_FOCUSED:
|
||||
lv_keyboard_set_textarea(kb, ta);
|
||||
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(kb);
|
||||
break;
|
||||
case LV_EVENT_DEFOCUSED:
|
||||
lv_keyboard_set_textarea(kb, NULL);
|
||||
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OmoteUI::create_keyboard()
|
||||
{
|
||||
void OmoteUI::create_keyboard() {
|
||||
this->kb = lv_keyboard_create(lv_scr_act());
|
||||
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_set_y(this->kb, 0);
|
||||
}
|
||||
|
||||
void OmoteUI::hide_keyboard()
|
||||
{
|
||||
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
void OmoteUI::hide_keyboard() { lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); }
|
||||
|
||||
void OmoteUI::reset_settings_menu()
|
||||
{
|
||||
void OmoteUI::reset_settings_menu() {
|
||||
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
|
||||
}
|
||||
|
||||
void OmoteUI::attach_keyboard(lv_obj_t* textarea)
|
||||
{
|
||||
if (this->kb == NULL)
|
||||
{
|
||||
void OmoteUI::attach_keyboard(lv_obj_t *textarea) {
|
||||
if (this->kb == NULL) {
|
||||
this->create_keyboard();
|
||||
}
|
||||
lv_keyboard_set_textarea(this->kb, textarea);
|
||||
lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_FOCUSED, this->kb);
|
||||
lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_DEFOCUSED, this->kb);
|
||||
lv_obj_add_event_cb(
|
||||
textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); },
|
||||
LV_EVENT_FOCUSED, this->kb);
|
||||
lv_obj_add_event_cb(
|
||||
textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); },
|
||||
LV_EVENT_DEFOCUSED, this->kb);
|
||||
}
|
||||
|
||||
void OmoteUI::layout_UI() {
|
||||
|
||||
// Set the background color
|
||||
// Set the background color
|
||||
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
|
||||
this->create_keyboard();
|
||||
// Setup a scrollable tabview for devices and settings
|
||||
lv_obj_t* tabview;
|
||||
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
|
||||
lv_obj_t *tabview;
|
||||
tabview =
|
||||
lv_tabview_create(lv_scr_act(), LV_DIR_TOP,
|
||||
0); // Hide tab labels by setting their height to 0
|
||||
lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_size(tabview, SCREEN_WIDTH, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
|
||||
lv_obj_set_size(tabview, SCREEN_WIDTH,
|
||||
270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
|
||||
lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20);
|
||||
|
||||
// Add 4 tabs (names are irrelevant since the labels are hidden)
|
||||
lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings");
|
||||
lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat");
|
||||
lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV");
|
||||
lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home");
|
||||
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Settings");
|
||||
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Technisat");
|
||||
lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Apple TV");
|
||||
lv_obj_t *tab4 = lv_tabview_add_tab(tabview, "Smart Home");
|
||||
|
||||
// Configure number button grid
|
||||
static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution
|
||||
static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit
|
||||
// Configure number button grid
|
||||
static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1),
|
||||
LV_GRID_TEMPLATE_LAST}; // equal x distribution
|
||||
static lv_coord_t row_dsc[] = {
|
||||
52, 52, 52, 52, LV_GRID_TEMPLATE_LAST}; // manual y distribution to
|
||||
// compress the grid a bit
|
||||
|
||||
// Create a container with grid for tab2
|
||||
lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN);
|
||||
lv_obj_t* cont = lv_obj_create(tab2);
|
||||
lv_obj_t *cont = lv_obj_create(tab2);
|
||||
lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
|
||||
|
@ -251,48 +267,57 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* buttonLabel;
|
||||
lv_obj_t* obj;
|
||||
lv_obj_t *buttonLabel;
|
||||
lv_obj_t *obj;
|
||||
|
||||
// Iterate through grid buttons configure them
|
||||
for (int i = 0; i < 12; i++) {
|
||||
uint8_t col = i % 3;
|
||||
uint8_t row = i / 3;
|
||||
// Create the button object
|
||||
if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
|
||||
if ((row == 3) && ((col == 0) || (col == 2)))
|
||||
continue; // Do not create a complete fourth row, only a 0 button
|
||||
obj = lv_btn_create(cont);
|
||||
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1);
|
||||
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
|
||||
LV_GRID_ALIGN_STRETCH, row, 1);
|
||||
lv_obj_set_style_bg_color(obj, this->color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(obj, 14, LV_PART_MAIN);
|
||||
lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes
|
||||
// a event in its container
|
||||
// Create Labels for each button
|
||||
buttonLabel = lv_label_create(obj);
|
||||
if(i < 9){
|
||||
lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row);
|
||||
lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
|
||||
}
|
||||
else{
|
||||
buttonLabel = lv_label_create(obj);
|
||||
if (i < 9) {
|
||||
lv_label_set_text_fmt(buttonLabel, std::to_string(i + 1).c_str(), col,
|
||||
row);
|
||||
lv_obj_set_user_data(obj,
|
||||
(void *)i); // Add user data so we can identify which
|
||||
// button caused the container event
|
||||
} else {
|
||||
lv_label_set_text_fmt(buttonLabel, "0", col, row);
|
||||
lv_obj_set_user_data(obj, (void*)9);
|
||||
}
|
||||
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN);
|
||||
lv_obj_set_user_data(obj, (void *)9);
|
||||
}
|
||||
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24,
|
||||
LV_PART_MAIN);
|
||||
lv_obj_center(buttonLabel);
|
||||
}
|
||||
// Create a shared event for all button inside container
|
||||
lv_obj_add_event_cb(cont, [] (lv_event_t* e) {mInstance->virtualKeypad_event_cb(e);}, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
lv_obj_add_event_cb(
|
||||
cont, [](lv_event_t *e) { mInstance->virtualKeypad_event_cb(e); },
|
||||
LV_EVENT_CLICKED, NULL);
|
||||
|
||||
// Add content to the Apple TV tab (3)
|
||||
// Add a nice apple tv logo
|
||||
lv_obj_t* appleImg = imgs.addAppleTVIcon(tab3);
|
||||
lv_obj_t *appleImg = imgs.addAppleTVIcon(tab3);
|
||||
// create two buttons and add their icons accordingly
|
||||
lv_obj_t* button = lv_btn_create(tab3);
|
||||
lv_obj_t *button = lv_btn_create(tab3);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)1);
|
||||
lv_obj_add_event_cb(
|
||||
button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); },
|
||||
LV_EVENT_CLICKED, (void *)1);
|
||||
|
||||
appleImg = imgs.addAppleDisplayImage(button);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
|
||||
|
@ -305,7 +330,9 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)2);
|
||||
lv_obj_add_event_cb(
|
||||
button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); },
|
||||
LV_EVENT_CLICKED, (void *)2);
|
||||
|
||||
appleImg = imgs.addAppleDisplayImage(button);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
|
||||
|
@ -321,39 +348,49 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the light controls
|
||||
lv_obj_t* menuLabel = lv_label_create(tab4);
|
||||
lv_obj_t *menuLabel = lv_label_create(tab4);
|
||||
lv_label_set_text(menuLabel, "Living Room");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(tab4);
|
||||
lv_obj_t *menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* bulbIcon = imgs.addLightBulbIcon(menuBox);
|
||||
lv_obj_t *bulbIcon = imgs.addLightBulbIcon(menuBox);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Floor Lamp");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleA = lv_switch_create(menuBox);
|
||||
lv_obj_t *lightToggleA = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleA, 40, 22);
|
||||
lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50),
|
||||
LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleA, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
lv_obj_add_event_cb(
|
||||
lightToggleA,
|
||||
[](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, (void *)1);
|
||||
|
||||
lv_obj_t *slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30),
|
||||
LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(
|
||||
slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180),
|
||||
LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
|
||||
LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
lv_obj_add_event_cb(
|
||||
slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, (void *)1);
|
||||
|
||||
// Add another this->settingsMenu box for a second appliance
|
||||
menuBox = lv_obj_create(tab4);
|
||||
|
@ -367,26 +404,35 @@ void OmoteUI::layout_UI() {
|
|||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Ceiling Light");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleB = lv_switch_create(menuBox);
|
||||
lv_obj_t *lightToggleB = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleB, 40, 22);
|
||||
lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50),
|
||||
LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleB, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
lv_obj_add_event_cb(
|
||||
lightToggleB,
|
||||
[](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, (void *)2);
|
||||
|
||||
slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30),
|
||||
LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(
|
||||
slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180),
|
||||
LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
|
||||
LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
lv_obj_add_event_cb(
|
||||
slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, (void *)2);
|
||||
|
||||
// Add another room (empty for now)
|
||||
menuLabel = lv_label_create(tab4);
|
||||
|
@ -397,21 +443,20 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
|
||||
// Set current page according to the current Device
|
||||
currentDevice = this->mHardware->getCurrentDevice();
|
||||
lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF);
|
||||
|
||||
|
||||
// Create a page indicator
|
||||
panel = lv_obj_create(lv_scr_act());
|
||||
lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
|
||||
lv_obj_clear_flag(
|
||||
panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
|
||||
lv_obj_set_size(panel, SCREEN_WIDTH, 30);
|
||||
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_t *btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
@ -419,7 +464,7 @@ void OmoteUI::layout_UI() {
|
|||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Settings");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
|
@ -456,10 +501,15 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
|
||||
// Make the indicator scroll together with the tabs by creating a scroll event
|
||||
lv_obj_add_event_cb(lv_tabview_get_content(tabview), [] (lv_event_t* e) {mInstance->store_scroll_value_event_cb(e);}, LV_EVENT_SCROLL, NULL);
|
||||
lv_obj_add_event_cb(tabview, [] (lv_event_t* e) {mInstance->tabview_device_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_add_event_cb(
|
||||
lv_tabview_get_content(tabview),
|
||||
[](lv_event_t *e) { mInstance->store_scroll_value_event_cb(e); },
|
||||
LV_EVENT_SCROLL, NULL);
|
||||
lv_obj_add_event_cb(
|
||||
tabview, [](lv_event_t *e) { mInstance->tabview_device_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, NULL);
|
||||
// Initialize scroll position for the indicator
|
||||
lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL);
|
||||
|
||||
|
@ -472,10 +522,10 @@ void OmoteUI::layout_UI() {
|
|||
lv_obj_add_style(panel, &style_btn, 0);
|
||||
|
||||
// Make the indicator fade out at the sides using gradient bitmaps
|
||||
lv_obj_t* img1 = imgs.addLeftGradiant(lv_scr_act());
|
||||
lv_obj_t *img1 = imgs.addLeftGradiant(lv_scr_act());
|
||||
lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
|
||||
lv_obj_t* img2 = imgs.addRightGradiant(lv_scr_act());
|
||||
lv_obj_t *img2 = imgs.addRightGradiant(lv_scr_act());
|
||||
lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_obj_set_size(img2, 30, 30);
|
||||
|
|
@ -2,18 +2,19 @@
|
|||
// 2023 Matthew Colvin
|
||||
#pragma once
|
||||
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "Images.hpp"
|
||||
#include "UIBase.hpp"
|
||||
#include "lvgl.h"
|
||||
#include "poller.hpp"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "poller.hpp"
|
||||
|
||||
namespace UI::Basic {
|
||||
/// @brief Singleton to allow UI code to live separately from the Initialization
|
||||
/// of resources.
|
||||
class OmoteUI {
|
||||
class OmoteUI : public UIBase {
|
||||
public:
|
||||
OmoteUI(std::shared_ptr<HardwareAbstract> aHardware);
|
||||
|
||||
|
@ -47,86 +48,88 @@ public:
|
|||
void smartHomeSlider_event_cb(lv_event_t *e);
|
||||
// Virtual Keypad Event handler
|
||||
void virtualKeypad_event_cb(lv_event_t *e);
|
||||
void wifi_settings_cb(lv_event_t* event);
|
||||
void wifi_settings_cb(lv_event_t *event);
|
||||
|
||||
void connect_btn_cb(lv_event_t* event);
|
||||
void connect_btn_cb(lv_event_t *event);
|
||||
|
||||
void password_field_event_cb(lv_event_t* e);
|
||||
void password_field_event_cb(lv_event_t *e);
|
||||
// Use LVGL to layout the ui and register the callbacks
|
||||
void layout_UI();
|
||||
|
||||
void ta_kb_event_cb(lv_event_t* e);
|
||||
void ta_kb_event_cb(lv_event_t *e);
|
||||
|
||||
void wifi_scan_done(std::shared_ptr<std::vector<WifiInfo>> info);
|
||||
void loopHandler();
|
||||
/**
|
||||
* @brief Function to hide the keyboard. If the keyboard is attached to a text area, it will be hidden when the
|
||||
* text area is defocused. This function can be used if the keyboard need to be hidden due to some script event.
|
||||
*
|
||||
* @brief Function to hide the keyboard. If the keyboard is attached to a text
|
||||
* area, it will be hidden when the text area is defocused. This function can
|
||||
* be used if the keyboard need to be hidden due to some script event.
|
||||
*
|
||||
*/
|
||||
void hide_keyboard();
|
||||
|
||||
/**
|
||||
* @brief Function to show the keyboard. If a text area needs the keybaord, it should be attached to the text area
|
||||
* using the approbiate function. The keyboard will then show up when the text area is focused. This function is
|
||||
* @brief Function to show the keyboard. If a text area needs the keybaord, it
|
||||
* should be attached to the text area using the approbiate function. The
|
||||
* keyboard will then show up when the text area is focused. This function is
|
||||
* needed if the keyboard should be shown due to some script or other trigger.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void show_keyboard();
|
||||
|
||||
private:
|
||||
static std::shared_ptr<OmoteUI> mInstance;
|
||||
std::shared_ptr<HardwareAbstract> mHardware;
|
||||
|
||||
|
||||
std::unique_ptr<poller> batteryPoller;
|
||||
|
||||
|
||||
int sleepTimeoutMap[5] = {10000,30000,60000,180000,600000};
|
||||
|
||||
void reset_settings_menu();
|
||||
void attach_keyboard(lv_obj_t* textarea);
|
||||
void attach_keyboard(lv_obj_t *textarea);
|
||||
std::shared_ptr<std::vector<WifiInfo>> found_wifi_networks;
|
||||
/**
|
||||
* @brief Keyboard object used whenever a keyboard is needed.
|
||||
*
|
||||
*/
|
||||
lv_obj_t* kb;
|
||||
/**
|
||||
* @brief Keyboard object used whenever a keyboard is needed.
|
||||
*
|
||||
*/
|
||||
lv_obj_t *kb;
|
||||
|
||||
/**
|
||||
* @brief Function to create the keyboard object which can then be attached to different text areas.
|
||||
*
|
||||
*/
|
||||
void create_keyboard();
|
||||
/**
|
||||
* @brief Function to create the keyboard object which can then be attached to
|
||||
* different text areas.
|
||||
*
|
||||
*/
|
||||
void create_keyboard();
|
||||
|
||||
/**
|
||||
* @brief Set the up settings object
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* @param parent
|
||||
*/
|
||||
void setup_settings(lv_obj_t* parent);
|
||||
void setup_settings(lv_obj_t *parent);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief LVGL Menu for settings pages as needed.
|
||||
*
|
||||
*
|
||||
*/
|
||||
lv_obj_t* settingsMenu;
|
||||
lv_obj_t *settingsMenu;
|
||||
|
||||
/**
|
||||
* @brief Main page of the settings menu
|
||||
*
|
||||
* @brief Main page of the settings menu
|
||||
*
|
||||
*/
|
||||
lv_obj_t* settingsMainPage;
|
||||
lv_obj_t *settingsMainPage;
|
||||
|
||||
/**
|
||||
* @brief Battery percentage label
|
||||
*
|
||||
* @brief Battery percentage label
|
||||
*
|
||||
*/
|
||||
lv_obj_t* objBattPercentage;
|
||||
lv_obj_t *objBattPercentage;
|
||||
|
||||
/**
|
||||
* @brief Battery icon object in the status bar
|
||||
*
|
||||
* @brief Battery icon object in the status bar
|
||||
*
|
||||
*/
|
||||
lv_obj_t* objBattIcon;
|
||||
lv_obj_t *objBattIcon;
|
||||
|
||||
void create_status_bar();
|
||||
|
||||
|
@ -138,104 +141,110 @@ void create_keyboard();
|
|||
inline static const uint_fast8_t virtualKeyMapTechnisat[10] = {
|
||||
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0};
|
||||
|
||||
/************************************** WIFI Settings Menu *******************************************************/
|
||||
/************************************** WIFI Settings Menu
|
||||
* *******************************************************/
|
||||
/**
|
||||
* @brief Container within the wifi selection page
|
||||
*/
|
||||
lv_obj_t* wifi_setting_cont;
|
||||
lv_obj_t *wifi_setting_cont;
|
||||
|
||||
/**
|
||||
* @brief Wifi settings entry point on the settings tab
|
||||
*
|
||||
*
|
||||
*/
|
||||
lv_obj_t* wifiOverview;
|
||||
lv_obj_t *wifiOverview;
|
||||
|
||||
/**
|
||||
* @brief Label in the wifi password page. This label is updated with the selected SSID when the credentials for
|
||||
* a wifi network is entered.
|
||||
*
|
||||
* @brief Label in the wifi password page. This label is updated with the
|
||||
* selected SSID when the credentials for a wifi network is entered.
|
||||
*
|
||||
*/
|
||||
lv_obj_t* wifi_password_label;
|
||||
lv_obj_t *wifi_password_label;
|
||||
|
||||
/**
|
||||
* @brief Menu Subpage for the wifi password
|
||||
*/
|
||||
lv_obj_t* wifi_password_page;
|
||||
lv_obj_t *wifi_password_page;
|
||||
|
||||
/**
|
||||
* @brief Menu Subpage for wifi selection
|
||||
*/
|
||||
lv_obj_t* wifi_selection_page;
|
||||
lv_obj_t *wifi_selection_page;
|
||||
|
||||
/**
|
||||
* @brief Wifi Label shown in the top status bar
|
||||
*/
|
||||
lv_obj_t* WifiLabel;
|
||||
lv_obj_t *WifiLabel;
|
||||
|
||||
/**
|
||||
* @brief Number of wifi subpage needed to display the found wifi networks
|
||||
*
|
||||
*
|
||||
*/
|
||||
unsigned int no_subpages;
|
||||
|
||||
/**
|
||||
* @brief number of wifi networks found
|
||||
*
|
||||
*
|
||||
*/
|
||||
unsigned int no_wifi_networks;
|
||||
|
||||
|
||||
void wifi_status(std::shared_ptr<wifiStatus> status);
|
||||
/**
|
||||
* @brief callback function to get next wifi subpage. This callback can be used to get the next or previous page
|
||||
*
|
||||
* @param e lvgl event object
|
||||
* @brief callback function to get next wifi subpage. This callback can be
|
||||
* used to get the next or previous page
|
||||
*
|
||||
* @param e lvgl event object
|
||||
*/
|
||||
void next_wifi_selection_subpage(lv_event_t* e);
|
||||
void next_wifi_selection_subpage(lv_event_t *e);
|
||||
|
||||
/**
|
||||
* @brief Create a wifi selection sub page object
|
||||
*
|
||||
* @param menu LVGL Menu where the sub page should be added to
|
||||
*
|
||||
* @param menu LVGL Menu where the sub page should be added to
|
||||
* @return lv_obj_t* Menu sub page object pointer
|
||||
*/
|
||||
lv_obj_t* create_wifi_selection_page(lv_obj_t* menu);
|
||||
lv_obj_t *create_wifi_selection_page(lv_obj_t *menu);
|
||||
|
||||
/**
|
||||
* @brief Method to create the wifi password sub page
|
||||
*
|
||||
* @param menu Menu where the sub page should be created
|
||||
*
|
||||
* @param menu Menu where the sub page should be created
|
||||
* @return lv_obj_t* menu sub page object pointer
|
||||
*/
|
||||
lv_obj_t* create_wifi_password_page(lv_obj_t* menu);
|
||||
lv_obj_t *create_wifi_password_page(lv_obj_t *menu);
|
||||
|
||||
/**
|
||||
* @brief Method to create the wifi settings on the main page
|
||||
*
|
||||
* @param parent lv object parent where the main settings page should be added to
|
||||
*
|
||||
* @param parent lv object parent where the main settings page should be
|
||||
* added to
|
||||
*/
|
||||
void create_wifi_main_page(lv_obj_t* parent);
|
||||
void create_wifi_main_page(lv_obj_t *parent);
|
||||
|
||||
/**
|
||||
* @brief Method to create wifi settings. This method will call the create_wifi_selection_page,
|
||||
* the create_wifi_password_page, and the create_wifi_main_page
|
||||
*
|
||||
* @param menu Settings menu where the sub pages should be added to
|
||||
* @param parent lv object parent where the main settings page should be added to
|
||||
* @brief Method to create wifi settings. This method will call the
|
||||
* create_wifi_selection_page, the create_wifi_password_page, and the
|
||||
* create_wifi_main_page
|
||||
*
|
||||
* @param menu Settings menu where the sub pages should be added to
|
||||
* @param parent lv object parent where the main settings page should be
|
||||
* added to
|
||||
*/
|
||||
void create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent);
|
||||
|
||||
void create_wifi_settings(lv_obj_t *menu, lv_obj_t *parent);
|
||||
|
||||
/**
|
||||
* @brief Function to update the wifi selection sub page
|
||||
*
|
||||
* @param page index of the page to display
|
||||
*
|
||||
* @param page index of the page to display
|
||||
*/
|
||||
void update_wifi_selection_subpage(int page);
|
||||
|
||||
/**
|
||||
* @brief Function to create the display settings page.
|
||||
*
|
||||
*
|
||||
* @param parent LVGL object acting as a parent for the display settings page
|
||||
*/
|
||||
void display_settings(lv_obj_t* parent);
|
||||
void display_settings(lv_obj_t *parent);
|
||||
};
|
||||
|
||||
} // namespace UI::Basic
|
|
@ -1,61 +1,78 @@
|
|||
#include "OmoteUI.hpp"
|
||||
|
||||
void OmoteUI::display_settings(lv_obj_t* parent)
|
||||
{
|
||||
using namespace UI::Basic;
|
||||
|
||||
lv_obj_t* menuLabel = lv_label_create(parent);
|
||||
void OmoteUI::display_settings(lv_obj_t *parent) {
|
||||
|
||||
lv_obj_t *menuLabel = lv_label_create(parent);
|
||||
lv_label_set_text(menuLabel, "Display");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(parent);
|
||||
|
||||
lv_obj_t *menuBox = lv_obj_create(parent);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 109);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* brightnessIcon = imgs.addLowBrightnessIcon(menuBox);
|
||||
lv_obj_t *brightnessIcon = imgs.addLowBrightnessIcon(menuBox);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_t* slider = lv_slider_create(menuBox);
|
||||
lv_obj_t *slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 255);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, mHardware->display()->getBrightness() , LV_ANIM_OFF);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
|
||||
LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, mHardware->display()->getBrightness(),
|
||||
LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(66), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
|
||||
brightnessIcon = imgs.addHighBrightnessIcon(menuBox);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1);
|
||||
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->bl_slider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
|
||||
lv_obj_add_event_cb(
|
||||
slider, [](lv_event_t *e) { mInstance->bl_slider_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Lift to Wake");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
lv_obj_t* wakeToggle = lv_switch_create(menuBox);
|
||||
lv_obj_t *wakeToggle = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(wakeToggle, 40, 22);
|
||||
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
|
||||
lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(wakeToggle, [] (lv_event_t* e) {mInstance->WakeEnableSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(mHardware->getWakeupByIMUEnabled()) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
|
||||
lv_obj_add_event_cb(
|
||||
wakeToggle,
|
||||
[](lv_event_t *e) { mInstance->WakeEnableSetting_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if (mHardware->getWakeupByIMUEnabled())
|
||||
lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Timeout");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
|
||||
lv_obj_t* drop = lv_dropdown_create(menuBox);
|
||||
lv_obj_t *drop = lv_dropdown_create(menuBox);
|
||||
lv_dropdown_set_options(drop, "10s\n"
|
||||
"30s\n"
|
||||
"1m\n"
|
||||
"3m");
|
||||
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
|
||||
lv_obj_set_size(drop, 70, 22);
|
||||
//lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
//lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
// lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
// lv_obj_set_style_text_font(lv_dropdown_get_list(drop),
|
||||
// &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary,
|
||||
LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
int sleepTimeoutMapSize = sizeof(sleepTimeoutMap)/sizeof(sleepTimeoutMap[0]);
|
||||
lv_obj_set_style_border_color(lv_dropdown_get_list(drop),
|
||||
lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
|
||||
int sleepTimeoutMapSize =
|
||||
sizeof(sleepTimeoutMap) / sizeof(sleepTimeoutMap[0]);
|
||||
int currentTimeout = mHardware->getSleepTimeout();
|
||||
for(int i = 0; i < sleepTimeoutMapSize; i++){
|
||||
if(currentTimeout == sleepTimeoutMap[i]) lv_dropdown_set_selected(drop, i);
|
||||
for (int i = 0; i < sleepTimeoutMapSize; i++) {
|
||||
if (currentTimeout == sleepTimeoutMap[i])
|
||||
lv_dropdown_set_selected(drop, i);
|
||||
}
|
||||
lv_obj_add_event_cb(drop, [] (lv_event_t* e) {mInstance->wakeTimeoutSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_add_event_cb(
|
||||
drop, [](lv_event_t *e) { mInstance->wakeTimeoutSetting_event_cb(e); },
|
||||
LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
#define WIFI_SUBPAGE_SIZE 3
|
||||
static char* ssid;
|
||||
|
||||
using namespace UI::Basic;
|
||||
|
||||
lv_obj_t* OmoteUI::create_wifi_selection_page(lv_obj_t* menu)
|
||||
{
|
||||
/* Create sub page for wifi*/
|
21
Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp
Normal file
21
Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "BasicUI.hpp"
|
||||
#include "HardwareFactory.hpp"
|
||||
#include "HomeScreen.hpp"
|
||||
#include "ScreenManager.hpp"
|
||||
|
||||
using namespace UI;
|
||||
|
||||
BasicUI::BasicUI() : UIBase() {
|
||||
|
||||
HardwareFactory::getAbstract().keys()->RegisterKeyPressHandler(
|
||||
[](auto aKeyEvent) {
|
||||
return Screen::Manager::getInstance().distributeKeyEvent(aKeyEvent);
|
||||
// Could potentially add a check here and display that a key event was
|
||||
// unused.
|
||||
});
|
||||
|
||||
Screen::Manager::getInstance().pushScreen(
|
||||
std::make_unique<Screen::HomeScreen>());
|
||||
|
||||
HardwareFactory::getAbstract().wifi()->begin();
|
||||
}
|
11
Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp
Normal file
11
Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
#include "UIBase.hpp"
|
||||
|
||||
namespace UI {
|
||||
|
||||
class BasicUI : public UIBase {
|
||||
public:
|
||||
BasicUI();
|
||||
};
|
||||
|
||||
} // namespace UI
|
51
Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp
Normal file
51
Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "Demo.hpp"
|
||||
#include "Slider.hpp"
|
||||
|
||||
using namespace UI::Page;
|
||||
|
||||
Demo::Demo() : Base(ID::Pages::Demo) {}
|
||||
|
||||
void Demo::AddSlider() {
|
||||
auto fakeSlider = std::make_unique<Widget::Slider>([](auto data) {});
|
||||
fakeSlider->SetHeight(lv_pct(10));
|
||||
fakeSlider->SetWidth(GetContentWidth());
|
||||
if (sliders.empty()) {
|
||||
fakeSlider->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
} else {
|
||||
auto nextY = sliders.back()->GetY() + sliders.back()->GetHeight();
|
||||
fakeSlider->SetY(nextY + 10);
|
||||
}
|
||||
|
||||
sliders.push_back(AddElement(std::move(fakeSlider)));
|
||||
}
|
||||
|
||||
bool Demo::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
using id = KeyPressAbstract::KeyId;
|
||||
using eventType = KeyPressAbstract::KeyEvent::Type;
|
||||
bool used = true;
|
||||
switch (aKeyEvent.mId) {
|
||||
case id::Aux1:
|
||||
if (aKeyEvent.mType == eventType::Press) {
|
||||
AddSlider();
|
||||
}
|
||||
break;
|
||||
case id::Aux2:
|
||||
if (aKeyEvent.mType == eventType::Release) {
|
||||
if (sliders.size() > 0) {
|
||||
RemoveElement(sliders[0]);
|
||||
sliders.erase(
|
||||
sliders.begin()); // sliders is non owning so after removing delete
|
||||
// it from non owning array
|
||||
}
|
||||
}
|
||||
break;
|
||||
case id::Aux3:
|
||||
break;
|
||||
case id::Aux4:
|
||||
break;
|
||||
default:
|
||||
used = Page::Base::OnKeyEvent(aKeyEvent);
|
||||
break;
|
||||
}
|
||||
return used;
|
||||
}
|
20
Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp
Normal file
20
Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include "PageBase.hpp"
|
||||
|
||||
namespace UI::Page {
|
||||
|
||||
class Demo : public Base {
|
||||
public:
|
||||
Demo();
|
||||
|
||||
void AddSlider();
|
||||
|
||||
void OnShow() override{};
|
||||
void OnHide() override{};
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
|
||||
|
||||
private:
|
||||
std::vector<UIElement *> sliders;
|
||||
};
|
||||
|
||||
} // namespace UI::Page
|
|
@ -0,0 +1,16 @@
|
|||
#include "DisplaySettings.hpp"
|
||||
#include "BrightnessSlider.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
using namespace UI::Page;
|
||||
|
||||
DisplaySettings::DisplaySettings(std::shared_ptr<DisplayAbstract> aDisplay)
|
||||
: Base(UI::ID::Pages::DisplaySettings), mDisplay(aDisplay),
|
||||
mBrightnessSlider(AddElement<Widget::BrightnessSlider>(
|
||||
std::make_unique<Widget::BrightnessSlider>(mDisplay))) {
|
||||
SetBgColor(Color::GREY);
|
||||
|
||||
mBrightnessSlider->SetWidth(GetContentWidth());
|
||||
mBrightnessSlider->SetHeight(80);
|
||||
mBrightnessSlider->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "DisplayAbstract.h"
|
||||
#include "DropDown.hpp"
|
||||
#include "PageBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class BrightnessSlider;
|
||||
} // namespace UI::Widget
|
||||
|
||||
namespace UI::Page {
|
||||
class DisplaySettings : public Base {
|
||||
public:
|
||||
DisplaySettings(std::shared_ptr<DisplayAbstract> aDisplay);
|
||||
|
||||
std::string GetTitle() override { return "Display Settings"; };
|
||||
|
||||
private:
|
||||
std::shared_ptr<DisplayAbstract> mDisplay;
|
||||
Widget::BrightnessSlider *mBrightnessSlider;
|
||||
};
|
||||
} // namespace UI::Page
|
43
Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp
Normal file
43
Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "SettingsPage.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include "Button.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "DisplaySettings.hpp"
|
||||
#include "HardwareFactory.hpp"
|
||||
#include "List.hpp"
|
||||
#include "PopUpScreen.hpp"
|
||||
#include "ScreenManager.hpp"
|
||||
#include "Slider.hpp"
|
||||
#include "SystemSettings.hpp"
|
||||
#include "WifiSettings.hpp"
|
||||
|
||||
using namespace UI::Page;
|
||||
using namespace UI::Color;
|
||||
|
||||
SettingsPage::SettingsPage()
|
||||
: Base(ID::Pages::Settings), mSettingsList(AddElement<Widget::List>(
|
||||
std::make_unique<Widget::List>())) {
|
||||
|
||||
mSettingsList->AddItem("Display", LV_SYMBOL_EYE_OPEN,
|
||||
[this] { PushDisplaySettings(); });
|
||||
mSettingsList->AddItem("Wifi", LV_SYMBOL_WIFI,
|
||||
[this] { PushWifiSettings(); });
|
||||
mSettingsList->AddItem("System", LV_SYMBOL_SETTINGS,
|
||||
[this] { PushSystemSettings(); });
|
||||
}
|
||||
|
||||
void SettingsPage::PushDisplaySettings() {
|
||||
UI::Screen::Manager::getInstance().pushPopUp(
|
||||
std::make_unique<DisplaySettings>(
|
||||
HardwareFactory::getAbstract().display()));
|
||||
}
|
||||
|
||||
void SettingsPage::PushSystemSettings() {
|
||||
UI::Screen::Manager::getInstance().pushPopUp(
|
||||
std::make_unique<SystemSettings>());
|
||||
}
|
||||
|
||||
void SettingsPage::PushWifiSettings() {
|
||||
UI::Screen::Manager::getInstance().pushPopUp(
|
||||
std::make_unique<WifiSettings>(HardwareFactory::getAbstract().wifi()));
|
||||
}
|
28
Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp
Normal file
28
Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "HardwareAbstract.hpp"
|
||||
#include "PageBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class Button;
|
||||
class List;
|
||||
} // namespace UI::Widget
|
||||
namespace UI::Page {
|
||||
class SettingsPage : public Base {
|
||||
public:
|
||||
SettingsPage();
|
||||
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override {
|
||||
return false;
|
||||
};
|
||||
|
||||
void PushDisplaySettings();
|
||||
void PushSystemSettings();
|
||||
void PushWifiSettings();
|
||||
|
||||
protected:
|
||||
void OnShow() override{};
|
||||
void OnHide() override{};
|
||||
|
||||
Widget::Button *mButton;
|
||||
Widget::List *mSettingsList;
|
||||
};
|
||||
} // namespace UI::Page
|
|
@ -0,0 +1,27 @@
|
|||
#include "SystemSettings.hpp"
|
||||
#include "HardwareFactory.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
using namespace UI::Page;
|
||||
|
||||
SystemSettings::SystemSettings()
|
||||
: Base(ID::Pages::SystemSettings),
|
||||
mTimeoutLabel(AddElement<Widget::Label>(
|
||||
std::make_unique<Widget::Label>("TimeOut"))),
|
||||
mScreenTimeOutDropDown(AddElement<Widget::DropDown<int>>(
|
||||
std::make_unique<Widget::DropDown<int>>([this](int aTimeout) {
|
||||
HardwareFactory::getAbstract().setSleepTimeout(aTimeout);
|
||||
}))) {
|
||||
|
||||
mTimeoutLabel->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
mTimeoutLabel->SetHeight(15);
|
||||
|
||||
mScreenTimeOutDropDown->SetHeight(30);
|
||||
mScreenTimeOutDropDown->SetWidth(GetContentWidth());
|
||||
mScreenTimeOutDropDown->AddItem("10 Seconds", 10000);
|
||||
mScreenTimeOutDropDown->AddItem("15 Seconds", 15000);
|
||||
mScreenTimeOutDropDown->AddItem("20 Seconds", 20000);
|
||||
mScreenTimeOutDropDown->AlignTo(mTimeoutLabel, LV_ALIGN_OUT_BOTTOM_MID);
|
||||
mScreenTimeOutDropDown->SetSelected(
|
||||
HardwareFactory::getAbstract().getSleepTimeout());
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
#include "DropDown.hpp"
|
||||
#include "PageBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class Label;
|
||||
}
|
||||
|
||||
namespace UI::Page {
|
||||
|
||||
class SystemSettings : public Base {
|
||||
public:
|
||||
SystemSettings();
|
||||
|
||||
protected:
|
||||
std::string GetTitle() override { return "System Settings"; }
|
||||
|
||||
private:
|
||||
Widget::Label *mTimeoutLabel;
|
||||
Widget::DropDown<int> *mScreenTimeOutDropDown;
|
||||
};
|
||||
|
||||
} // namespace UI::Page
|
79
Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp
Normal file
79
Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "WifiSettings.hpp"
|
||||
#include "Keyboard.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "List.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
|
||||
using namespace UI;
|
||||
using namespace UI::Page;
|
||||
|
||||
WifiSettings::WifiSettings(std::shared_ptr<wifiHandlerInterface> aWifi)
|
||||
: Base(ID::Pages::WifiSettings), mWifi(aWifi),
|
||||
mScanCompleteHandler(mWifi->ScanCompleteNotification()),
|
||||
mScanStatusHandler(mWifi->WifiStatusNotification()),
|
||||
mScanningText(AddElement<Widget::Label>(
|
||||
std::make_unique<Widget::Label>("Scanning..."))),
|
||||
mWifiNetworks(AddElement<Widget::List>(std::make_unique<Widget::List>())),
|
||||
mPasswordGetter(nullptr) {
|
||||
|
||||
// Set Handler for when the wifi scan is done
|
||||
mScanCompleteHandler = [this](auto aWifiInfos) {
|
||||
if (aWifiInfos.empty()) {
|
||||
mScanningText->SetText("No Networks Found");
|
||||
return;
|
||||
}
|
||||
mScanningText->SetText("Networks Found");
|
||||
// Create List of wifi infos that when pressed a Keyboard opens
|
||||
for (WifiInfo wifiInfo : aWifiInfos) {
|
||||
mWifiNetworks->AddItem(wifiInfo.ssid, LV_SYMBOL_WIFI, [this, wifiInfo] {
|
||||
OpenPasswordKeyboard(wifiInfo);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
mWifi->scan();
|
||||
}
|
||||
|
||||
void WifiSettings::OpenPasswordKeyboard(WifiInfo aNetworkToConnectTo) {
|
||||
// We already have a Keyboard don't launch another one.
|
||||
if (mPasswordGetter) {
|
||||
return;
|
||||
}
|
||||
auto keyboard = std::make_unique<Widget::Keyboard>(
|
||||
[this, aNetworkToConnectTo](auto aUserEnteredPassword) {
|
||||
// Attempt Connection when user finishes up with keyboard input
|
||||
mWifi->connect(aNetworkToConnectTo.ssid, aUserEnteredPassword);
|
||||
mScanningText->SetText("Attempting Connection to " +
|
||||
aNetworkToConnectTo.ssid);
|
||||
mPasswordGetter->AnimateOut();
|
||||
StartHandlingStatusUpdates();
|
||||
},
|
||||
"Password:");
|
||||
keyboard->OnKeyboardAnimatedOut([this] {
|
||||
// Keyboard is done animating out remove it and null the ref
|
||||
RemoveElement(mPasswordGetter);
|
||||
mPasswordGetter = nullptr;
|
||||
});
|
||||
mPasswordGetter = AddElement<Widget::Keyboard>(std::move(keyboard));
|
||||
}
|
||||
|
||||
void WifiSettings::StartHandlingStatusUpdates() {
|
||||
mScanStatusHandler = [this](auto aWifiStatus) {
|
||||
if (aWifiStatus.isConnected) {
|
||||
mScanningText->SetText("Connected to " + aWifiStatus.ssid);
|
||||
} else {
|
||||
mScanningText->SetText("Failed To Connect To " + aWifiStatus.ssid);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void WifiSettings::SetHeight(lv_coord_t aHeight) {
|
||||
Base::SetHeight(aHeight);
|
||||
mScanningText->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
mScanningText->SetHeight(20);
|
||||
mScanningText->SetLongMode(LV_LABEL_LONG_SCROLL);
|
||||
const auto padding = 10;
|
||||
mWifiNetworks->AlignTo(mScanningText, LV_ALIGN_OUT_BOTTOM_MID, 0, padding);
|
||||
mWifiNetworks->SetHeight(GetContentHeight() - mScanningText->GetBottom() -
|
||||
padding);
|
||||
};
|
37
Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp
Normal file
37
Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
#include "PageBase.hpp"
|
||||
#include "wifiHandlerInterface.h"
|
||||
|
||||
namespace UI::Widget {
|
||||
class List;
|
||||
class Label;
|
||||
class Keyboard;
|
||||
} // namespace UI::Widget
|
||||
|
||||
namespace UI::Page {
|
||||
class WifiSettings : public Base {
|
||||
using WifiInfo = wifiHandlerInterface::WifiInfo;
|
||||
public:
|
||||
WifiSettings(std::shared_ptr<wifiHandlerInterface> aWifi);
|
||||
|
||||
std::string GetTitle() override { return "Wifi Settings"; };
|
||||
|
||||
void SetHeight(lv_coord_t aHeight) override;
|
||||
|
||||
protected:
|
||||
void StartHandlingStatusUpdates();
|
||||
|
||||
void OpenPasswordKeyboard(WifiInfo aNetworkToConnectTo);
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<wifiHandlerInterface> mWifi;
|
||||
Handler<wifiHandlerInterface::ScanDoneDataTy> mScanCompleteHandler;
|
||||
Handler<wifiHandlerInterface::wifiStatus> mScanStatusHandler;
|
||||
|
||||
UI::Widget::Label *mScanningText;
|
||||
UI::Widget::List *mWifiNetworks;
|
||||
UI::Widget::Keyboard *mPasswordGetter;
|
||||
};
|
||||
|
||||
} // namespace UI::Page
|
28
Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp
Normal file
28
Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "HomeScreen.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "Demo.hpp"
|
||||
#include "SettingsPage.hpp"
|
||||
|
||||
using namespace UI::Screen;
|
||||
|
||||
HomeScreen::HomeScreen()
|
||||
: Base(UI::ID::Screens::Home),
|
||||
mTabView(AddElement<Page::TabView>(
|
||||
std::make_unique<Page::TabView>(ID(ID::Pages::INVALID_PAGE_ID)))) {
|
||||
|
||||
SetBgColor(UI::Color::BLACK);
|
||||
SetPushAnimation(LV_SCR_LOAD_ANIM_FADE_IN);
|
||||
|
||||
// Adds pages to the Tab view
|
||||
mTabView->AddTab(std::make_unique<Page::SettingsPage>());
|
||||
mTabView->AddTab(std::make_unique<Page::Demo>());
|
||||
}
|
||||
|
||||
void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) {
|
||||
mTabView->SetBgColor(value, selector);
|
||||
UI::UIElement::SetBgColor(value, selector);
|
||||
}
|
||||
|
||||
bool HomeScreen::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
return false;
|
||||
};
|
23
Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp
Normal file
23
Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "PageBase.hpp"
|
||||
#include "ScreenBase.hpp"
|
||||
#include "TabView.hpp"
|
||||
#include <string>
|
||||
namespace UI::Screen {
|
||||
|
||||
class HomeScreen : public Base {
|
||||
public:
|
||||
HomeScreen();
|
||||
|
||||
void SetBgColor(lv_color_t value,
|
||||
lv_style_selector_t selector = LV_PART_MAIN) override;
|
||||
|
||||
protected:
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
private:
|
||||
Page::TabView *mTabView;
|
||||
};
|
||||
|
||||
} // namespace UI::Screen
|
|
@ -0,0 +1,44 @@
|
|||
#include "BrightnessSlider.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "Slider.hpp"
|
||||
|
||||
using namespace UI::Widget;
|
||||
|
||||
BrightnessSlider::BrightnessSlider(std::shared_ptr<DisplayAbstract> aDisplay)
|
||||
: Base(ID::Widgets::BrightnessSlider), mDisplay(aDisplay),
|
||||
mSlider(AddElement<Widget::Slider>(std::make_unique<Slider>(
|
||||
[this](auto aNewBrightness) {
|
||||
mDisplay->setBrightness(aNewBrightness);
|
||||
},
|
||||
0, 255))),
|
||||
mLabel(AddElement<Widget::Label>(std::make_unique<Label>("Brightness"))) {
|
||||
mLabel->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
mSlider->AlignTo(mLabel, LV_ALIGN_OUT_BOTTOM_MID);
|
||||
mSlider->SetWidth(GetContentWidth() - GetContentWidth() * 0.25f);
|
||||
}
|
||||
|
||||
void BrightnessSlider::OnShow() {
|
||||
mSlider->SetValue(mDisplay->getBrightness());
|
||||
Base::OnShow();
|
||||
}
|
||||
|
||||
void BrightnessSlider::SetHeight(lv_coord_t aHeight) {
|
||||
Base::SetHeight(aHeight);
|
||||
auto labelHeight = 12;
|
||||
auto sliderHeight = aHeight * 0.60f - labelHeight;
|
||||
mLabel->SetHeight(labelHeight);
|
||||
mSlider->SetHeight(sliderHeight);
|
||||
mLabel->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
mSlider->AlignTo(mLabel, LV_ALIGN_OUT_BOTTOM_MID, 0,
|
||||
mLabel->GetContentHeight());
|
||||
}
|
||||
|
||||
bool BrightnessSlider::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
using ID = KeyPressAbstract::KeyId;
|
||||
using Type = KeyPressAbstract::KeyEvent::Type;
|
||||
if (aKeyEvent.mId == ID::Aux1 && aKeyEvent.mType == Type::Press) {
|
||||
SetVisiblity(!IsSetVisible());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
#include "DisplayAbstract.h"
|
||||
#include "WidgetBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class Slider;
|
||||
class Label;
|
||||
|
||||
class BrightnessSlider : public Base {
|
||||
public:
|
||||
BrightnessSlider(std::shared_ptr<DisplayAbstract> aDisplay);
|
||||
|
||||
void SetHeight(lv_coord_t aHeight) override;
|
||||
|
||||
protected:
|
||||
void OnShow() override;
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DisplayAbstract> mDisplay;
|
||||
Slider *mSlider;
|
||||
Label *mLabel;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
1180
Platformio/OmoteUI/UIs/Images.cpp
Normal file
1180
Platformio/OmoteUI/UIs/Images.cpp
Normal file
File diff suppressed because it is too large
Load diff
48
Platformio/OmoteUI/UIs/Images.hpp
Normal file
48
Platformio/OmoteUI/UIs/Images.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
// OMOTE UI Images
|
||||
// 2023 Matthew Colvin
|
||||
#pragma once
|
||||
#include "lvgl.h"
|
||||
|
||||
class Images {
|
||||
|
||||
public:
|
||||
Images();
|
||||
|
||||
lv_obj_t *addAppleTVIcon(lv_obj_t *parent);
|
||||
lv_obj_t *addAppleDisplayImage(lv_obj_t *parent);
|
||||
lv_obj_t *addAppleBackIcon(lv_obj_t *parent);
|
||||
|
||||
lv_obj_t *addLowBrightnessIcon(lv_obj_t *parent);
|
||||
lv_obj_t *addHighBrightnessIcon(lv_obj_t *parent);
|
||||
lv_obj_t *addLightBulbIcon(lv_obj_t *parent);
|
||||
|
||||
lv_obj_t *addLeftGradiant(lv_obj_t *parent);
|
||||
lv_obj_t *addRightGradiant(lv_obj_t *parent);
|
||||
|
||||
lv_obj_t *addWifiNoSignal(lv_obj_t *parent);
|
||||
lv_obj_t *addWifiLowSignal(lv_obj_t *parent);
|
||||
lv_obj_t *addWifiMidSignal(lv_obj_t *parent);
|
||||
lv_obj_t *addWifiHighSignal(lv_obj_t *parent);
|
||||
|
||||
private:
|
||||
// Make Image based on anImageDesc then
|
||||
// add that image to parent.
|
||||
lv_obj_t *addImg(lv_obj_t *parent, lv_img_dsc_t *anImgDesc);
|
||||
void setupImageDescriptions();
|
||||
|
||||
lv_img_dsc_t appleTvIcon;
|
||||
lv_img_dsc_t appleDisplayIcon;
|
||||
lv_img_dsc_t appleBackIcon;
|
||||
|
||||
lv_img_dsc_t low_brightness;
|
||||
lv_img_dsc_t high_brightness;
|
||||
lv_img_dsc_t lightbulb_icon;
|
||||
|
||||
lv_img_dsc_t gradientLeft;
|
||||
lv_img_dsc_t gradientRight;
|
||||
|
||||
lv_img_dsc_t wifiNoSignal;
|
||||
lv_img_dsc_t wifiLowSignal;
|
||||
lv_img_dsc_t wifiMidSignal;
|
||||
lv_img_dsc_t wifiHighSignal;
|
||||
};
|
49
Platformio/OmoteUI/UIs/LvglResourceManager.hpp
Normal file
49
Platformio/OmoteUI/UIs/LvglResourceManager.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
namespace UI {
|
||||
class UIBase;
|
||||
} // namespace UI
|
||||
|
||||
class LvglResourceManager {
|
||||
friend UI::UIBase;
|
||||
|
||||
public:
|
||||
static LvglResourceManager &GetInstance() {
|
||||
static LvglResourceManager mInstance;
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::scoped_lock<std::recursive_mutex> scopeLock() {
|
||||
return std::scoped_lock(mLvglMutex);
|
||||
}
|
||||
|
||||
void AttemptNow(std::function<void()> aLvglModifierFunction) {
|
||||
// Attempt to take mutex and preform op if you can't then queue up.
|
||||
if (mLvglMutex.try_lock()) {
|
||||
aLvglModifierFunction();
|
||||
mLvglMutex.unlock();
|
||||
} else {
|
||||
QueueForLater(aLvglModifierFunction);
|
||||
}
|
||||
}
|
||||
void QueueForLater(std::function<void()> aLvglModifierFunction) {
|
||||
mLvglTasks.push(std::move(aLvglModifierFunction));
|
||||
}
|
||||
|
||||
protected:
|
||||
LvglResourceManager(){};
|
||||
|
||||
void HandleQueuedTasks() {
|
||||
auto lock = scopeLock();
|
||||
while (!mLvglTasks.empty()) {
|
||||
mLvglTasks.front()();
|
||||
mLvglTasks.pop();
|
||||
}
|
||||
}
|
||||
|
||||
std::queue<std::function<void()>> mLvglTasks;
|
||||
std::recursive_mutex mLvglMutex;
|
||||
};
|
15
Platformio/OmoteUI/UIs/UIBase.cpp
Normal file
15
Platformio/OmoteUI/UIs/UIBase.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "UIBase.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
|
||||
using namespace UI;
|
||||
|
||||
UIBase::UIBase() {}
|
||||
|
||||
void UIBase::loopHandler() {
|
||||
{
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_timer_handler();
|
||||
lv_task_handler();
|
||||
}
|
||||
LvglResourceManager::GetInstance().HandleQueuedTasks();
|
||||
}
|
19
Platformio/OmoteUI/UIs/UIBase.hpp
Normal file
19
Platformio/OmoteUI/UIs/UIBase.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
// OMOTE UI
|
||||
// 2023 Matthew Colvin
|
||||
|
||||
#pragma once
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace UI {
|
||||
|
||||
class UIBase {
|
||||
public:
|
||||
UIBase();
|
||||
|
||||
virtual void loopHandler();
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
} // namespace UI
|
40
Platformio/OmoteUI/core/Animation.cpp
Normal file
40
Platformio/OmoteUI/core/Animation.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "Animation.hpp"
|
||||
|
||||
using namespace UI;
|
||||
|
||||
Animation::Animation(std::function<void(int32_t)> aAnimator,
|
||||
int32_t aAnimationTime, int32_t aStart, int32_t aEnd)
|
||||
: mAnimator(aAnimator), mStart(aStart), mEnd(aEnd) {
|
||||
lv_anim_init(&mAnimation);
|
||||
mAnimation.user_data = this;
|
||||
lv_anim_set_custom_exec_cb(&mAnimation, AnimatorImpl);
|
||||
lv_anim_set_time(&mAnimation, aAnimationTime);
|
||||
}
|
||||
|
||||
Animation::~Animation() { lv_anim_custom_del(&mAnimation, AnimatorImpl); }
|
||||
|
||||
void Animation::HandleAnimationComplete(
|
||||
std::function<void()> onAnimationComplete) {
|
||||
mOnComplete = onAnimationComplete;
|
||||
}
|
||||
|
||||
void Animation::Start() {
|
||||
lv_anim_set_values(&mAnimation, mStart, mEnd);
|
||||
lv_anim_start(&mAnimation);
|
||||
}
|
||||
|
||||
void Animation::Reverse() {
|
||||
std::swap(mStart, mEnd);
|
||||
Start();
|
||||
}
|
||||
|
||||
//////////////////////// Statics /////////////////////////////////////////
|
||||
|
||||
void Animation::AnimatorImpl(lv_anim_t *aSelf, int32_t aNextValue) {
|
||||
auto self = reinterpret_cast<Animation *>(aSelf->user_data);
|
||||
self->mAnimator(aNextValue);
|
||||
// TODO This probably will not support Overshoot animations.
|
||||
if (self->mOnComplete && aNextValue == self->mEnd) {
|
||||
self->mOnComplete();
|
||||
}
|
||||
}
|
31
Platformio/OmoteUI/core/Animation.hpp
Normal file
31
Platformio/OmoteUI/core/Animation.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
class Animation {
|
||||
public:
|
||||
Animation(std::function<void(int32_t)> aAnimator, int32_t aAnimationTime,
|
||||
int32_t aStart = 0, int32_t aEnd = 100);
|
||||
|
||||
virtual ~Animation();
|
||||
|
||||
void HandleAnimationComplete(std::function<void()> onAnimationComplete);
|
||||
|
||||
void Start();
|
||||
void Reverse();
|
||||
|
||||
private:
|
||||
lv_anim_t mAnimation;
|
||||
std::function<void(int32_t)> mAnimator = nullptr;
|
||||
std::function<void()> mOnComplete = nullptr;
|
||||
bool onCompleteCalled = false;
|
||||
|
||||
int32_t mStart = 0;
|
||||
int32_t mEnd = 0;
|
||||
|
||||
static void AnimatorImpl(lv_anim_t *aSelf, int32_t aNextValue);
|
||||
};
|
||||
|
||||
} // namespace UI
|
110
Platformio/OmoteUI/core/BorderOutlinePadding.hpp
Normal file
110
Platformio/OmoteUI/core/BorderOutlinePadding.hpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
#include "Colors.hpp"
|
||||
#include "UIElement.hpp"
|
||||
#include <lvgl.h>
|
||||
// Builder Class to make it easier to create boarder and Paddings
|
||||
namespace UI {
|
||||
/////////////////////////////////Border/////////////////////////////////
|
||||
class Border {
|
||||
friend class UIElement;
|
||||
|
||||
public:
|
||||
Border() = default;
|
||||
|
||||
Border &Width(lv_coord_t aWidth) {
|
||||
width = aWidth;
|
||||
return *this;
|
||||
}
|
||||
Border &Color(lv_color_t aColor) {
|
||||
color = aColor;
|
||||
return *this;
|
||||
}
|
||||
Border &Opacity(lv_opa_t aOpacity) {
|
||||
opacity = aOpacity;
|
||||
return *this;
|
||||
}
|
||||
Border &Sides(lv_border_side_t aSides) {
|
||||
sides = aSides;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
lv_coord_t width = 0;
|
||||
lv_color_t color = UI::Color::BLACK;
|
||||
lv_opa_t opacity = 255;
|
||||
lv_border_side_t sides = LV_BORDER_SIDE_FULL;
|
||||
};
|
||||
|
||||
///////////////////////////////////////Outline////////////////////////////////
|
||||
class Outline {
|
||||
friend class UIElement;
|
||||
|
||||
public:
|
||||
Outline() = default;
|
||||
|
||||
Outline &Width(lv_coord_t aWidth) {
|
||||
width = aWidth;
|
||||
return *this;
|
||||
}
|
||||
Outline &Color(lv_color_t aColor) {
|
||||
color = aColor;
|
||||
return *this;
|
||||
}
|
||||
Outline &Opacity(lv_opa_t aOpacity) {
|
||||
opacity = aOpacity;
|
||||
return *this;
|
||||
}
|
||||
Outline &Padding(lv_coord_t aPadding) {
|
||||
padding = aPadding;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
lv_coord_t width = 0;
|
||||
lv_color_t color = UI::Color::BLACK;
|
||||
lv_opa_t opacity = 255;
|
||||
lv_coord_t padding = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////Padding////////////////////////////////
|
||||
class Padding {
|
||||
friend class UIElement;
|
||||
|
||||
public:
|
||||
Padding() = default;
|
||||
|
||||
Padding &Top(lv_coord_t aTopPadding) {
|
||||
top = aTopPadding;
|
||||
return *this;
|
||||
};
|
||||
Padding &Bottom(lv_coord_t aBottomPadding) {
|
||||
bottom = aBottomPadding;
|
||||
return *this;
|
||||
};
|
||||
Padding &Left(lv_coord_t aLeftPadding) {
|
||||
left = aLeftPadding;
|
||||
return *this;
|
||||
};
|
||||
Padding &Right(lv_coord_t aRightPadding) {
|
||||
right = aRightPadding;
|
||||
return *this;
|
||||
};
|
||||
Padding &Row(lv_coord_t aRowPadding) {
|
||||
row = aRowPadding;
|
||||
return *this;
|
||||
}
|
||||
Padding &Column(lv_coord_t aColumnPadding) {
|
||||
column = aColumnPadding;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
lv_coord_t top = 0;
|
||||
lv_coord_t bottom = 0;
|
||||
lv_coord_t left = 0;
|
||||
lv_coord_t right = 0;
|
||||
lv_coord_t row = 0;
|
||||
lv_coord_t column = 0;
|
||||
};
|
||||
|
||||
} // namespace UI
|
16
Platformio/OmoteUI/core/Colors.hpp
Normal file
16
Platformio/OmoteUI/core/Colors.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace UI::Color {
|
||||
const auto WHITE = lv_color_white();
|
||||
const auto BLACK = lv_color_black();
|
||||
const auto RED = lv_color_make(255, 0, 0);
|
||||
const auto GREEN = lv_color_make(0, 255, 0);
|
||||
const auto BLUE = lv_color_make(0, 0, 255);
|
||||
|
||||
const auto PURPLE = lv_color_make(128, 0, 128);
|
||||
const auto LILAC = lv_color_make(231, 209, 255);
|
||||
|
||||
const auto GREY = lv_color_make(105, 105, 105);
|
||||
|
||||
} // namespace UI::Color
|
62
Platformio/OmoteUI/core/ScreenManager.cpp
Normal file
62
Platformio/OmoteUI/core/ScreenManager.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "ScreenManager.hpp"
|
||||
#include "PopUpScreen.hpp"
|
||||
|
||||
using namespace UI::Screen;
|
||||
|
||||
Manager Manager::mManager = Manager();
|
||||
|
||||
Manager &Manager::getInstance() { return mManager; }
|
||||
|
||||
Manager::Manager() {}
|
||||
|
||||
void Manager::pushScreen(Screen::Base::Ptr aScreen) {
|
||||
if (!mScreens.empty()) {
|
||||
mScreens.back()->OnHide();
|
||||
}
|
||||
mScreens.push_back(std::move(aScreen));
|
||||
mScreens.back()->Show();
|
||||
}
|
||||
|
||||
void Manager::pushScreen(Screen::Base::Ptr aScreen,
|
||||
lv_scr_load_anim_t aPushAnimation) {
|
||||
aScreen->SetPushAnimation(aPushAnimation);
|
||||
pushScreen(std::move(aScreen));
|
||||
}
|
||||
|
||||
void Manager::pushPopUp(Page::Base::Ptr aPopUpPage,
|
||||
lv_scr_load_anim_t aPushAnimation) {
|
||||
pushScreen(std::make_unique<PopUpScreen>(std::move(aPopUpPage)),
|
||||
aPushAnimation);
|
||||
}
|
||||
|
||||
UI::Screen::Base::Ptr Manager::popScreen(Screen::Base *aScreenToRemove) {
|
||||
auto screenToPop = std::find_if(
|
||||
mScreens.begin(), mScreens.end(), [aScreenToRemove](auto &screenInStack) {
|
||||
return screenInStack.get() == aScreenToRemove;
|
||||
});
|
||||
|
||||
bool isPopOffTopOfStack = mScreens.end() - 1 == screenToPop;
|
||||
Screen::Base::Ptr retVal = nullptr;
|
||||
if (screenToPop != mScreens.end()) {
|
||||
retVal = std::move(*screenToPop);
|
||||
mScreens.erase(screenToPop);
|
||||
if (isPopOffTopOfStack) {
|
||||
// Make sure to show correct top of stack
|
||||
// since we popped the top screen off
|
||||
mScreens.back()->Show();
|
||||
// Make sure to notify the screen that just got moved off top
|
||||
retVal->OnHide();
|
||||
// In order to make sure the Transition can complete
|
||||
// flag the removed screen to stay alive in case it falls
|
||||
// out of scope and gets deleted quickly after this.
|
||||
retVal->SetKeepAliveTime(mScreens.back()->GetTransitionTime() + 500);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool Manager::distributeKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
// Send Key Even to top Screen for handling
|
||||
return mScreens.back()->KeyEvent(aKeyEvent);
|
||||
}
|
33
Platformio/OmoteUI/core/ScreenManager.hpp
Normal file
33
Platformio/OmoteUI/core/ScreenManager.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "PageBase.hpp"
|
||||
#include "ScreenBase.hpp"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace UI::Screen {
|
||||
|
||||
class Manager {
|
||||
public:
|
||||
static Manager &getInstance();
|
||||
|
||||
void pushScreen(Screen::Base::Ptr aScreen);
|
||||
void pushScreen(Screen::Base::Ptr aScreen,
|
||||
lv_scr_load_anim_t aPushAnimationOverride);
|
||||
|
||||
void
|
||||
pushPopUp(UI::Page::Base::Ptr aPopUpPage,
|
||||
lv_scr_load_anim_t aPushAnimation = LV_SCR_LOAD_ANIM_OVER_LEFT);
|
||||
|
||||
Screen::Base::Ptr popScreen(Screen::Base *aScreenToRemove);
|
||||
|
||||
bool distributeKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
|
||||
|
||||
private:
|
||||
Manager();
|
||||
static Manager mManager;
|
||||
|
||||
std::vector<Screen::Base::Ptr> mScreens;
|
||||
};
|
||||
|
||||
} // namespace UI::Screen
|
52
Platformio/OmoteUI/core/TextStyle.hpp
Normal file
52
Platformio/OmoteUI/core/TextStyle.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
#include "Colors.hpp"
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace UI {
|
||||
class UIElement;
|
||||
|
||||
class TextStyle {
|
||||
friend UIElement;
|
||||
|
||||
public:
|
||||
TextStyle() = default;
|
||||
|
||||
TextStyle &Opacity(lv_opa_t aOpacity) {
|
||||
opacity = aOpacity;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &Color(lv_color_t aColor) {
|
||||
color = aColor;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &Decor(lv_text_decor_t aDecor) {
|
||||
decor = aDecor;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &Align(lv_text_align_t aAlignment) {
|
||||
align = aAlignment;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &LetterSpacing(lv_coord_t aLetterSpacing) {
|
||||
letter_space = aLetterSpacing;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &LineSpacing(lv_coord_t aLineSpacing) {
|
||||
line_space = aLineSpacing;
|
||||
return *this;
|
||||
}
|
||||
TextStyle &Font(const lv_font_t *aFont) {
|
||||
font = aFont;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
lv_opa_t opacity = 255;
|
||||
lv_color_t color = Color::WHITE;
|
||||
lv_text_decor_t decor = LV_TEXT_DECOR_NONE;
|
||||
lv_text_align_t align = LV_TEXT_ALIGN_CENTER;
|
||||
lv_coord_t letter_space = 0;
|
||||
lv_coord_t line_space = 0;
|
||||
const lv_font_t *font = lv_font_default();
|
||||
};
|
||||
} // namespace UI
|
333
Platformio/OmoteUI/core/UIElement.cpp
Normal file
333
Platformio/OmoteUI/core/UIElement.cpp
Normal file
|
@ -0,0 +1,333 @@
|
|||
#include "UIElement.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
|
||||
namespace UI {
|
||||
UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId)
|
||||
: mLvglSelf(aLvglSelf), mId(aId) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
mLvglSelf->user_data = this;
|
||||
// Register Handler so that all object are able to override OnLvglEvent to
|
||||
// handle events easilyOnLvEvent
|
||||
lv_obj_add_event_cb(mLvglSelf, UIElement::LvglEventHandler, LV_EVENT_ALL,
|
||||
this);
|
||||
}
|
||||
|
||||
UIElement::~UIElement() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
if (lv_obj_is_valid(LvglSelf())) {
|
||||
if (mLvglKeepAliveTime > 0) {
|
||||
lv_obj_del_delayed(LvglSelf(), mLvglKeepAliveTime);
|
||||
} else {
|
||||
lv_obj_del(LvglSelf());
|
||||
}
|
||||
lv_obj_remove_event_cb(mLvglSelf, UIElement::LvglEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
UIElement *UIElement::GetParent() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
if (auto parent = lv_obj_get_parent(mLvglSelf); parent) {
|
||||
if (auto parentElem = parent->user_data; parentElem) {
|
||||
return reinterpret_cast<UIElement *>(parentElem);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UIElement *UIElement::AddElement(UIElement::Ptr anUIElement) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf);
|
||||
anUIElement->OnAdded(this);
|
||||
if (IsVisible() && anUIElement->IsSetVisible()) {
|
||||
anUIElement->OnShow();
|
||||
}
|
||||
mContainedElements.push_back(std::move(anUIElement));
|
||||
return mContainedElements[mContainedElements.size() - 1].get();
|
||||
}
|
||||
|
||||
UIElement::Ptr UIElement::RemoveElement(UIElement *anElementRef) {
|
||||
auto ElemToRemoveIter =
|
||||
std::find_if(mContainedElements.begin(), mContainedElements.end(),
|
||||
[anElementRef](auto &anElement) {
|
||||
return anElement.get() == anElementRef;
|
||||
});
|
||||
if (ElemToRemoveIter != mContainedElements.end()) {
|
||||
auto widget = std::move(*ElemToRemoveIter);
|
||||
mContainedElements.erase(ElemToRemoveIter);
|
||||
return widget;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UIElement::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
if (OnKeyEvent(aKeyEvent)) {
|
||||
return true;
|
||||
}
|
||||
for (auto &elem : mContainedElements) {
|
||||
if (elem->KeyEvent(aKeyEvent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
bool UIElement::IsVisible() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return lv_obj_is_visible(mLvglSelf);
|
||||
}
|
||||
|
||||
bool UIElement::IsSetVisible() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return !lv_obj_has_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void UIElement::SetWidth(lv_coord_t aWidth) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aWidth] { lv_obj_set_width(mLvglSelf, aWidth); });
|
||||
}
|
||||
|
||||
void UIElement::SetHeight(lv_coord_t aHeight) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aHeight] { lv_obj_set_height(mLvglSelf, aHeight); });
|
||||
}
|
||||
|
||||
lv_coord_t UIElement::GetHeight() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_height(mLvglSelf);
|
||||
};
|
||||
|
||||
lv_coord_t UIElement::GetWidth() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_width(mLvglSelf);
|
||||
}
|
||||
|
||||
void UIElement::SetContentWidth(lv_coord_t aWidth) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aWidth] { lv_obj_set_content_width(mLvglSelf, aWidth); });
|
||||
}
|
||||
void UIElement::SetContentHeight(lv_coord_t aHeight) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aHeight] { lv_obj_set_content_height(mLvglSelf, aHeight); });
|
||||
}
|
||||
|
||||
lv_coord_t UIElement::GetContentWidth() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_content_width(mLvglSelf);
|
||||
}
|
||||
lv_coord_t UIElement::GetContentHeight() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_content_height(mLvglSelf);
|
||||
}
|
||||
|
||||
void UIElement::SetY(lv_coord_t aY) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aY] { lv_obj_set_y(mLvglSelf, aY); });
|
||||
};
|
||||
void UIElement::SetX(lv_coord_t aX) {
|
||||
LvglResourceManager::GetInstance().AttemptNow(
|
||||
[this, aX] { lv_obj_set_x(mLvglSelf, aX); });
|
||||
}
|
||||
|
||||
lv_coord_t UIElement::GetY() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_y(mLvglSelf);
|
||||
}
|
||||
lv_coord_t UIElement::GetX() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_update_layout(mLvglSelf);
|
||||
return lv_obj_get_x(mLvglSelf);
|
||||
}
|
||||
|
||||
lv_coord_t UIElement::GetBottom() { return GetY() + GetHeight(); };
|
||||
|
||||
void UIElement::SetBorder(Border aNewBorder, lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aNewBorder, aStyle] {
|
||||
lv_obj_set_style_border_color(mLvglSelf, aNewBorder.color, aStyle);
|
||||
lv_obj_set_style_border_opa(mLvglSelf, aNewBorder.opacity, aStyle);
|
||||
lv_obj_set_style_border_side(mLvglSelf, aNewBorder.sides, aStyle);
|
||||
lv_obj_set_style_border_width(mLvglSelf, aNewBorder.width, aStyle);
|
||||
});
|
||||
}
|
||||
|
||||
Border UIElement::GetBorder(lv_style_selector_t aStyle) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return Border()
|
||||
.Color(lv_obj_get_style_border_color(mLvglSelf, aStyle))
|
||||
.Opacity(lv_obj_get_style_border_opa(mLvglSelf, aStyle))
|
||||
.Sides(lv_obj_get_style_border_side(mLvglSelf, aStyle))
|
||||
.Width(lv_obj_get_style_border_width(mLvglSelf, aStyle));
|
||||
}
|
||||
|
||||
void UIElement::SetOutline(Outline aNewOutline, lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aNewOutline, aStyle] {
|
||||
lv_obj_set_style_outline_color(mLvglSelf, aNewOutline.color, aStyle);
|
||||
lv_obj_set_style_outline_opa(mLvglSelf, aNewOutline.opacity, aStyle);
|
||||
lv_obj_set_style_outline_width(mLvglSelf, aNewOutline.width, aStyle);
|
||||
lv_obj_set_style_outline_pad(mLvglSelf, aNewOutline.padding, aStyle);
|
||||
});
|
||||
};
|
||||
|
||||
Outline UIElement::GetOutline(lv_style_selector_t aStyle) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return Outline()
|
||||
.Color(lv_obj_get_style_outline_color(mLvglSelf, aStyle))
|
||||
.Opacity(lv_obj_get_style_outline_opa(mLvglSelf, aStyle))
|
||||
.Padding(lv_obj_get_style_outline_pad(mLvglSelf, aStyle))
|
||||
.Width(lv_obj_get_style_outline_width(mLvglSelf, aStyle));
|
||||
};
|
||||
|
||||
void UIElement::SetPadding(Padding aNewPadding, lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aNewPadding, aStyle] {
|
||||
lv_obj_set_style_pad_top(mLvglSelf, aNewPadding.top, aStyle);
|
||||
lv_obj_set_style_pad_bottom(mLvglSelf, aNewPadding.bottom, aStyle);
|
||||
lv_obj_set_style_pad_left(mLvglSelf, aNewPadding.left, aStyle);
|
||||
lv_obj_set_style_pad_right(mLvglSelf, aNewPadding.right, aStyle);
|
||||
lv_obj_set_style_pad_row(mLvglSelf, aNewPadding.row, aStyle);
|
||||
lv_obj_set_style_pad_column(mLvglSelf, aNewPadding.column, aStyle);
|
||||
});
|
||||
};
|
||||
|
||||
void UIElement::SetAllPadding(lv_coord_t aNewPadding,
|
||||
lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aNewPadding, aStyle] {
|
||||
lv_obj_set_style_pad_all(mLvglSelf, aNewPadding, aStyle);
|
||||
});
|
||||
}
|
||||
|
||||
Padding UIElement::GetPadding(lv_style_selector_t aStyle) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return Padding()
|
||||
.Top(lv_obj_get_style_pad_top(mLvglSelf, aStyle))
|
||||
.Bottom(lv_obj_get_style_pad_bottom(mLvglSelf, aStyle))
|
||||
.Left(lv_obj_get_style_pad_left(mLvglSelf, aStyle))
|
||||
.Right(lv_obj_get_style_pad_right(mLvglSelf, aStyle))
|
||||
.Row(lv_obj_get_style_pad_row(mLvglSelf, aStyle))
|
||||
.Column(lv_obj_get_style_pad_column(mLvglSelf, aStyle));
|
||||
};
|
||||
|
||||
void UIElement::SetTextStyle(TextStyle aNewTextStyle,
|
||||
lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aNewTextStyle, aStyle] {
|
||||
lv_obj_set_style_text_align(mLvglSelf, aNewTextStyle.align, aStyle);
|
||||
lv_obj_set_style_text_color(mLvglSelf, aNewTextStyle.color, aStyle);
|
||||
lv_obj_set_style_text_decor(mLvglSelf, aNewTextStyle.decor, aStyle);
|
||||
lv_obj_set_style_text_font(mLvglSelf, aNewTextStyle.font, aStyle);
|
||||
lv_obj_set_style_text_letter_space(mLvglSelf, aNewTextStyle.letter_space,
|
||||
aStyle);
|
||||
lv_obj_set_style_text_line_space(mLvglSelf, aNewTextStyle.line_space,
|
||||
aStyle);
|
||||
lv_obj_set_style_text_opa(mLvglSelf, aNewTextStyle.opacity, aStyle);
|
||||
});
|
||||
}
|
||||
|
||||
TextStyle UIElement::GetTextStyle(lv_style_selector_t aStyle) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return TextStyle()
|
||||
.Align(lv_obj_get_style_text_align(mLvglSelf, aStyle))
|
||||
.Color(lv_obj_get_style_text_color(mLvglSelf, aStyle))
|
||||
.Decor(lv_obj_get_style_text_decor(mLvglSelf, aStyle))
|
||||
.Font(lv_obj_get_style_text_font(mLvglSelf, aStyle))
|
||||
.LetterSpacing(lv_obj_get_style_text_letter_space(mLvglSelf, aStyle))
|
||||
.LineSpacing(lv_obj_get_style_text_line_space(mLvglSelf, aStyle))
|
||||
.Opacity(lv_obj_get_style_text_opa(mLvglSelf, aStyle));
|
||||
}
|
||||
|
||||
void UIElement::AlignTo(UIElement *anElementToAlignTo, lv_align_t anAlignment,
|
||||
lv_coord_t aXoffset, lv_coord_t aYOffset) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([=] {
|
||||
lv_obj_align_to(mLvglSelf, anElementToAlignTo->mLvglSelf, anAlignment,
|
||||
aXoffset, aYOffset);
|
||||
});
|
||||
}
|
||||
|
||||
void UIElement::SetVisiblity(bool aVisible) {
|
||||
if (aVisible == !lv_obj_has_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN)) {
|
||||
return;
|
||||
}
|
||||
if (aVisible) {
|
||||
Show();
|
||||
} else {
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
void UIElement::SetBgColor(lv_color_t aColor, lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aColor, aStyle] {
|
||||
lv_obj_set_style_bg_color(mLvglSelf, aColor, aStyle);
|
||||
});
|
||||
};
|
||||
|
||||
void UIElement::SetBgOpacity(lv_opa_t aOpacity, lv_style_selector_t aStyle) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aOpacity, aStyle] {
|
||||
lv_obj_set_style_bg_opa(mLvglSelf, aOpacity, aStyle);
|
||||
});
|
||||
}
|
||||
|
||||
void UIElement::StartLvglEventHandler() {
|
||||
if (mIsHandlingLvglEvents) {
|
||||
return;
|
||||
}
|
||||
lv_obj_add_event_cb(mLvglSelf, UIElement::LvglEventHandler, LV_EVENT_ALL,
|
||||
this);
|
||||
mIsHandlingLvglEvents = true;
|
||||
}
|
||||
void UIElement::StopLvglEventHandler() {
|
||||
if (!mIsHandlingLvglEvents) {
|
||||
return;
|
||||
}
|
||||
lv_obj_remove_event_cb_with_user_data(mLvglSelf, UIElement::LvglEventHandler,
|
||||
this);
|
||||
mIsHandlingLvglEvents = false;
|
||||
}
|
||||
|
||||
void UIElement::Show() {
|
||||
if (IsSetVisible()) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_clear_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
OnShow();
|
||||
}
|
||||
|
||||
void UIElement::Hide() {
|
||||
if (!IsSetVisible()) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_obj_add_flag(mLvglSelf, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
OnHide();
|
||||
}
|
||||
|
||||
void UIElement::OnHide() {
|
||||
for (auto &elem : mContainedElements) {
|
||||
if (!IsSetVisible()) {
|
||||
elem->OnHide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIElement::OnShow() {
|
||||
for (auto &elem : mContainedElements) {
|
||||
if (IsSetVisible()) {
|
||||
elem->OnShow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////// Statics //////////////////////////
|
||||
|
||||
void UIElement::LvglEventHandler(lv_event_t *anEvent) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
reinterpret_cast<UIElement *>(anEvent->user_data)->OnLvglEvent(anEvent);
|
||||
}
|
||||
|
||||
} // namespace UI
|
176
Platformio/OmoteUI/core/UIElement.hpp
Normal file
176
Platformio/OmoteUI/core/UIElement.hpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
#pragma once
|
||||
|
||||
#include "BorderOutlinePadding.hpp"
|
||||
#include "TextStyle.hpp"
|
||||
#include "UIElementIds.hpp"
|
||||
#include <lvgl.h>
|
||||
|
||||
#include "KeyPressAbstract.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace UI {
|
||||
|
||||
class UIElement {
|
||||
|
||||
public:
|
||||
using Ptr = std::unique_ptr<UIElement>;
|
||||
|
||||
UIElement(lv_obj_t *aLvglSelf, const ID aId = ID());
|
||||
virtual ~UIElement();
|
||||
|
||||
virtual void SetBgColor(lv_color_t value,
|
||||
lv_style_selector_t selector = LV_PART_MAIN);
|
||||
|
||||
virtual void SetBgOpacity(lv_opa_t aOpacity,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
|
||||
void SetVisiblity(bool aVisibility);
|
||||
bool IsVisible();
|
||||
bool IsSetVisible();
|
||||
|
||||
virtual void SetWidth(lv_coord_t aWidth);
|
||||
virtual void SetHeight(lv_coord_t aHeight);
|
||||
|
||||
lv_coord_t GetWidth();
|
||||
lv_coord_t GetHeight();
|
||||
|
||||
virtual void SetContentWidth(lv_coord_t aWidth);
|
||||
virtual void SetContentHeight(lv_coord_t aHeight);
|
||||
|
||||
lv_coord_t GetContentWidth();
|
||||
lv_coord_t GetContentHeight();
|
||||
|
||||
virtual void SetY(lv_coord_t aY);
|
||||
virtual void SetX(lv_coord_t aX);
|
||||
|
||||
lv_coord_t GetY();
|
||||
lv_coord_t GetX();
|
||||
lv_coord_t GetBottom();
|
||||
|
||||
void AlignTo(UIElement *anElementToAlignWith, lv_align_t anAlignment,
|
||||
lv_coord_t aXoffset = 0, lv_coord_t aYOffset = 0);
|
||||
|
||||
virtual void SetBorder(Border aNewBorder,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
Border GetBorder(lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
|
||||
virtual void SetOutline(Outline aNewOutline,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
Outline GetOutline(lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
|
||||
virtual void SetPadding(Padding aNewPadding,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
virtual void SetAllPadding(lv_coord_t aNewPadding,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
Padding GetPadding(lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
|
||||
virtual void SetTextStyle(TextStyle aNewStyle,
|
||||
lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
TextStyle GetTextStyle(lv_style_selector_t aStyle = LV_PART_MAIN);
|
||||
|
||||
UIElement *AddElement(UIElement::Ptr anElement);
|
||||
template <class UIElemTy> UIElemTy *AddElement(UIElement::Ptr aWidget);
|
||||
|
||||
UIElement::Ptr RemoveElement(UIElement *aUIElementRef);
|
||||
|
||||
size_t GetNumContainedElements() { return mContainedElements.size(); }
|
||||
|
||||
ID GetID() { return mId; };
|
||||
|
||||
template <class UIElemTy> static UIElemTy GetElement(lv_obj_t *aLvglObject);
|
||||
|
||||
/// @brief There are use cases in which objects
|
||||
/// need to stay alive in LVGL but can die
|
||||
/// in terms of our usage this is a helper for these
|
||||
/// use Sparingly!!!
|
||||
/// @param aTimeToKeepLvglObj
|
||||
void SetKeepAliveTime(uint32_t aTimeToKeepLvglObj) {
|
||||
mLvglKeepAliveTime = aTimeToKeepLvglObj;
|
||||
}
|
||||
|
||||
void StartLvglEventHandler();
|
||||
void StopLvglEventHandler();
|
||||
|
||||
/// @brief Register a callback to run for Lvgl Events for objects that
|
||||
/// are created from base classes.
|
||||
void OnLvglEvent(std::function<void(lv_event_t *anEvent)> aLvglEventHandler) {
|
||||
mLvglEventHandler = aLvglEventHandler;
|
||||
}
|
||||
|
||||
/// @brief get Lvgl object reference to use in LVGL APIs
|
||||
/// @return lvgl object a
|
||||
lv_obj_t *LvglSelf() { return mLvglSelf; }
|
||||
|
||||
protected:
|
||||
/// @brief Show Element
|
||||
virtual void Show();
|
||||
/// @brief Hide Element
|
||||
virtual void Hide();
|
||||
/// @brief Override in child class to run something after element is shown
|
||||
virtual void OnShow();
|
||||
/// @brief Override in child class to run something after element is hidden
|
||||
virtual void OnHide();
|
||||
|
||||
/// @brief Override to run something when element is added to a parent
|
||||
/// @param aNewParent - Parent UIElement just added to
|
||||
virtual void OnAdded(UIElement *aNewParent){};
|
||||
|
||||
// Override in object to handle LVGL events for that object
|
||||
virtual void OnLvglEvent(lv_event_t *anEvent) {
|
||||
if (mLvglEventHandler) {
|
||||
mLvglEventHandler(anEvent);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Set KeyEvent to the UI element to see if it wants to handle it
|
||||
virtual bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
|
||||
|
||||
/// @brief Override to Handle KeyEvent for the specific element
|
||||
/// @return true - Key event was used
|
||||
/// fasle - Key event was unused
|
||||
virtual bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) = 0;
|
||||
|
||||
private:
|
||||
/// @brief Get Pointer to Parent Element
|
||||
/// @return - nullptr Parent was not wrapped or did not exist
|
||||
UIElement *GetParent();
|
||||
|
||||
static void LvglEventHandler(lv_event_t *anEvent);
|
||||
|
||||
lv_obj_t *mLvglSelf;
|
||||
const ID mId;
|
||||
uint32_t mLvglKeepAliveTime = 0;
|
||||
bool mIsHandlingLvglEvents = true;
|
||||
std::function<void(lv_event_t *)> mLvglEventHandler = nullptr;
|
||||
|
||||
/// @brief Elements that are currently in this element
|
||||
std::vector<UIElement::Ptr> mContainedElements;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This helper allows conversion between anLvglObject and a
|
||||
* core element by using the user data that links the LVGL object
|
||||
* to its C++ counterpart. Do note that it is possible that this
|
||||
* user data is not always there if the Lvgl Object has not been wrapped
|
||||
* by UIElement
|
||||
*
|
||||
* @tparam UIElemTy - Type of element you want to cast to
|
||||
* @param aLvglObject - object to extract User data from
|
||||
* @return UIElemTy - object stored in user data (See constructor of
|
||||
* UIElement)
|
||||
*/
|
||||
template <class UIElemTy>
|
||||
UIElemTy UIElement::GetElement(lv_obj_t *aLvglObject) {
|
||||
auto UIElement = lv_obj_get_user_data(aLvglObject);
|
||||
if (UIElement) {
|
||||
return static_cast<UIElemTy>(UIElement);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class UIElemTy>
|
||||
UIElemTy *UIElement::AddElement(UIElement::Ptr anElement) {
|
||||
return static_cast<UIElemTy *>(AddElement(std::move(anElement)));
|
||||
}
|
||||
|
||||
} // namespace UI
|
45
Platformio/OmoteUI/core/UIElementIds.hpp
Normal file
45
Platformio/OmoteUI/core/UIElementIds.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
namespace UI {
|
||||
|
||||
class ID {
|
||||
public:
|
||||
static constexpr auto INVALID = 0;
|
||||
|
||||
enum class Screens {
|
||||
Background = static_cast<int>(INVALID) + 1,
|
||||
Home,
|
||||
PopUp,
|
||||
INVALID_SCREEN_ID
|
||||
};
|
||||
|
||||
enum class Widgets {
|
||||
Slider = static_cast<int>(Screens::INVALID_SCREEN_ID) + 1,
|
||||
Button,
|
||||
Label,
|
||||
List,
|
||||
DropDown,
|
||||
Keyboard,
|
||||
BrightnessSlider,
|
||||
INVALID_WIDGET_ID
|
||||
};
|
||||
|
||||
enum class Pages {
|
||||
Settings = static_cast<int>(Widgets::INVALID_WIDGET_ID) + 1,
|
||||
DisplaySettings,
|
||||
WifiSettings,
|
||||
SystemSettings,
|
||||
Demo,
|
||||
INVALID_PAGE_ID
|
||||
};
|
||||
|
||||
ID() : mId(INVALID){};
|
||||
ID(ID::Screens aScreenId) : mId(static_cast<int>(aScreenId)){};
|
||||
ID(ID::Widgets aWidgetId) : mId(static_cast<int>(aWidgetId)){};
|
||||
ID(ID::Pages aPageId) : mId(static_cast<int>(aPageId)){};
|
||||
|
||||
private:
|
||||
const int mId;
|
||||
};
|
||||
|
||||
} // namespace UI
|
13
Platformio/OmoteUI/core/page/PageBase.cpp
Normal file
13
Platformio/OmoteUI/core/page/PageBase.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "PageBase.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
|
||||
using namespace UI::Page;
|
||||
|
||||
Base::Base(ID aID)
|
||||
: Base(lv_obj_create(Screen::BackgroundScreen::getLvInstance()), aID) {}
|
||||
|
||||
Base::Base(lv_obj_t *aLvglSelf, ID aID) : UIElement(aLvglSelf, aID) {
|
||||
SetHeight(lv_pct(100));
|
||||
SetWidth(lv_pct(100));
|
||||
SetPadding(Padding()); // Set Padding to default
|
||||
}
|
36
Platformio/OmoteUI/core/page/PageBase.hpp
Normal file
36
Platformio/OmoteUI/core/page/PageBase.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include "UIElement.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
namespace UI::Screen {
|
||||
class PopUpScreen;
|
||||
}
|
||||
namespace UI::Page {
|
||||
class Tab;
|
||||
class TabView;
|
||||
class Base : public UIElement {
|
||||
// Classes that Own Pages
|
||||
friend Tab; // Allow Tab to Forward all Key Events to its page
|
||||
friend TabView; // Allow Tab view to call OnShow and OnHide Since it can show
|
||||
// and Hide pages by swiping
|
||||
friend UI::Screen::PopUpScreen; // Allow Pop up Screens pass events to the
|
||||
// page it owns
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<Base> Ptr;
|
||||
|
||||
Base(ID aID);
|
||||
Base(lv_obj_t *aLvglSelf, ID aID);
|
||||
virtual ~Base() = default;
|
||||
|
||||
// Override to have a title associated with your page.
|
||||
virtual std::string GetTitle() { return ""; };
|
||||
|
||||
protected:
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace UI::Page
|
62
Platformio/OmoteUI/core/page/TabView.cpp
Normal file
62
Platformio/OmoteUI/core/page/TabView.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "TabView.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace UI::Page;
|
||||
|
||||
Tab::Tab(lv_obj_t *aTab, Base::Ptr aContent) :
|
||||
Base(aTab, aContent->GetID()),
|
||||
mContent(AddElement<Base>(std::move(aContent))) {}
|
||||
|
||||
/////////////////////TabView/////////////////////////////////////
|
||||
|
||||
TabView::TabView(ID aId)
|
||||
: Base(lv_tabview_create(Screen::BackgroundScreen::getLvInstance(),
|
||||
LV_DIR_TOP, 0),
|
||||
aId) {}
|
||||
|
||||
void TabView::AddTab(Page::Base::Ptr aPage) {
|
||||
auto tab = std::make_unique<Tab>(
|
||||
lv_tabview_add_tab(LvglSelf(), aPage->GetTitle().c_str()), std::move(aPage));
|
||||
|
||||
mTabs.push_back(std::move(tab));
|
||||
}
|
||||
|
||||
uint16_t TabView::GetCurrentTabIdx() {
|
||||
return lv_tabview_get_tab_act(LvglSelf());
|
||||
}
|
||||
|
||||
void TabView::SetCurrentTabIdx(uint16_t aTabToSetActive,
|
||||
lv_anim_enable_t aIsDoAnimation) {
|
||||
lv_tabview_set_act(LvglSelf(), aTabToSetActive, aIsDoAnimation);
|
||||
}
|
||||
|
||||
void TabView::HandleTabChange() {
|
||||
// Call OnShow() for the page we just swapped to in order to
|
||||
// Notify the page that it is now showing and the other that the are now
|
||||
// hidden
|
||||
for (int i = 0; i < mTabs.size(); i++) {
|
||||
if (GetCurrentTabIdx() == i) {
|
||||
mTabs[i]->OnShow();
|
||||
} else {
|
||||
mTabs[i]->OnHide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TabView::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
if (OnKeyEvent(aKeyEvent)) {
|
||||
return true;
|
||||
}
|
||||
return mTabs[GetCurrentTabIdx()]->KeyEvent(aKeyEvent);
|
||||
};
|
||||
|
||||
void TabView::OnLvglEvent(lv_event_t *anEvent) {
|
||||
if (anEvent->code == LV_EVENT_VALUE_CHANGED) {
|
||||
HandleTabChange();
|
||||
}
|
||||
}
|
||||
|
||||
void TabView::OnShow() { mTabs[GetCurrentTabIdx()]->OnShow(); }
|
||||
|
||||
void TabView::OnHide() { mTabs[GetCurrentTabIdx()]->OnHide(); }
|
45
Platformio/OmoteUI/core/page/TabView.hpp
Normal file
45
Platformio/OmoteUI/core/page/TabView.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include "PageBase.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace UI::Page {
|
||||
class TabView;
|
||||
|
||||
class Tab : public Base {
|
||||
friend TabView;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<Tab> Ptr;
|
||||
|
||||
Tab(lv_obj_t *aTab, Base::Ptr aContent);
|
||||
|
||||
void OnShow() override{mContent->OnShow();};
|
||||
void OnHide() override{mContent->OnHide();};
|
||||
|
||||
private:
|
||||
Base* mContent;
|
||||
};
|
||||
|
||||
class TabView : public Base {
|
||||
public:
|
||||
TabView(ID aId);
|
||||
void AddTab(Page::Base::Ptr aPage);
|
||||
|
||||
uint16_t GetCurrentTabIdx();
|
||||
void SetCurrentTabIdx(uint16_t aTabToSetActive,
|
||||
lv_anim_enable_t aIsDoAnimation = LV_ANIM_ON);
|
||||
|
||||
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
void OnShow() override;
|
||||
void OnHide() override;
|
||||
|
||||
protected:
|
||||
void OnLvglEvent(lv_event_t *anEvent) override;
|
||||
|
||||
private:
|
||||
void HandleTabChange();
|
||||
|
||||
std::vector<Page::Tab::Ptr> mTabs;
|
||||
};
|
||||
|
||||
} // namespace UI::Page
|
28
Platformio/OmoteUI/core/poller.cpp
Normal file
28
Platformio/OmoteUI/core/poller.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "poller.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace UI;
|
||||
|
||||
poller::poller(std::function<void()> aOnPollCb, milliseconds aPollTime)
|
||||
: mIntermittentCallback(std::move(aOnPollCb)) {
|
||||
mTimer = lv_timer_create(poller::onPoll, aPollTime.count(), this);
|
||||
lv_timer_set_repeat_count(mTimer, -1); // Call forever
|
||||
}
|
||||
|
||||
poller::~poller() {
|
||||
if (mTimer) {
|
||||
lv_timer_del(mTimer);
|
||||
mTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void poller::onPoll(_lv_timer_t *aTimer) {
|
||||
poller *currentPoller = reinterpret_cast<poller *>(aTimer->user_data);
|
||||
|
||||
if (currentPoller->mIntermittentCallback) {
|
||||
currentPoller->mIntermittentCallback();
|
||||
}
|
||||
}
|
29
Platformio/OmoteUI/core/poller.hpp
Normal file
29
Platformio/OmoteUI/core/poller.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "lvgl.h"
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace UI {
|
||||
class poller {
|
||||
public:
|
||||
poller(std::function<void()> aOnPollCb,
|
||||
std::chrono::milliseconds pollTime = std::chrono::seconds(5));
|
||||
virtual ~poller();
|
||||
|
||||
void setPollPeriod(std::chrono::milliseconds aPollPeriod) {
|
||||
lv_timer_set_period(mTimer, aPollPeriod.count());
|
||||
}
|
||||
inline void pause() { lv_timer_pause(mTimer); }
|
||||
inline void resume() { lv_timer_resume(mTimer); }
|
||||
inline void reset() { lv_timer_reset(mTimer); }
|
||||
inline void runNext() { lv_timer_ready(mTimer); }
|
||||
|
||||
private:
|
||||
lv_timer_t *mTimer = nullptr;
|
||||
std::function<void()> mIntermittentCallback = nullptr;
|
||||
|
||||
// Static function registered to every timers callback to pass this object as
|
||||
// context
|
||||
static void onPoll(_lv_timer_t *aTimer);
|
||||
};
|
||||
} // namespace UI
|
18
Platformio/OmoteUI/core/screen/BackgroundScreen.cpp
Normal file
18
Platformio/OmoteUI/core/screen/BackgroundScreen.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "BackgroundScreen.hpp"
|
||||
|
||||
using namespace UI::Screen;
|
||||
|
||||
BackgroundScreen *BackgroundScreen::mInstance = nullptr;
|
||||
|
||||
BackgroundScreen *BackgroundScreen::GetInstance() {
|
||||
if (!mInstance) {
|
||||
mInstance = new BackgroundScreen();
|
||||
}
|
||||
return mInstance;
|
||||
};
|
||||
|
||||
lv_obj_t *BackgroundScreen::getLvInstance() {
|
||||
return GetInstance()->LvglSelf();
|
||||
}
|
||||
|
||||
BackgroundScreen::BackgroundScreen() : Base(ID::Screens::Background) {}
|
16
Platformio/OmoteUI/core/screen/BackgroundScreen.hpp
Normal file
16
Platformio/OmoteUI/core/screen/BackgroundScreen.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include "ScreenBase.hpp"
|
||||
namespace UI::Screen {
|
||||
/// @brief Due to the way LVGL utilizes screens we basically need a canvas to
|
||||
/// create new pages on
|
||||
/// by adding things to this screen and then moving them to their own page.
|
||||
class BackgroundScreen : Base {
|
||||
public:
|
||||
static BackgroundScreen *GetInstance();
|
||||
static lv_obj_t *getLvInstance();
|
||||
|
||||
private:
|
||||
BackgroundScreen();
|
||||
static BackgroundScreen *mInstance;
|
||||
};
|
||||
} // namespace UI::Screen
|
35
Platformio/OmoteUI/core/screen/PopUpScreen.cpp
Normal file
35
Platformio/OmoteUI/core/screen/PopUpScreen.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "PopUpScreen.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "ScreenManager.hpp"
|
||||
|
||||
using namespace UI;
|
||||
using namespace UI::Screen;
|
||||
|
||||
PopUpScreen::PopUpScreen(Page::Base::Ptr aPage)
|
||||
: Screen::Base(UI::ID::Screens::PopUp) {
|
||||
|
||||
mContentPage = AddElement<Page::Base>(std::move(aPage));
|
||||
|
||||
mExitButton = AddElement<Widget::Button>(std::make_unique<Widget::Button>(
|
||||
[this] { UI::Screen::Manager::getInstance().popScreen(this); }));
|
||||
|
||||
mTitle = AddElement<Widget::Label>(
|
||||
std::make_unique<Widget::Label>(mContentPage->GetTitle()));
|
||||
|
||||
mExitButton->SetWidth(lv_pct(10));
|
||||
mExitButton->SetHeight(mExitButton->GetWidth());
|
||||
mExitButton->SetBgColor(Color::RED);
|
||||
mExitButton->AlignTo(this, LV_ALIGN_TOP_RIGHT, -5, 5);
|
||||
|
||||
mTitle->SetWidth(mExitButton->GetX());
|
||||
mTitle->SetHeight(mExitButton->GetHeight());
|
||||
mTitle->AlignTo(mExitButton, LV_ALIGN_OUT_LEFT_BOTTOM);
|
||||
mTitle->SetTextStyle(mTitle->GetTextStyle().Align(LV_TEXT_ALIGN_CENTER));
|
||||
|
||||
mContentPage->SetHeight(GetHeight() - mExitButton->GetBottom() - 5);
|
||||
mContentPage->SetY(mExitButton->GetBottom() + 5);
|
||||
}
|
||||
|
||||
bool PopUpScreen::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
|
||||
return mContentPage->OnKeyEvent(aKeyEvent);
|
||||
}
|
23
Platformio/OmoteUI/core/screen/PopUpScreen.hpp
Normal file
23
Platformio/OmoteUI/core/screen/PopUpScreen.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
#include "Button.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "PageBase.hpp"
|
||||
#include "ScreenBase.hpp"
|
||||
|
||||
namespace UI::Screen {
|
||||
|
||||
/// @brief A Screen that allows easy display of a page that
|
||||
/// can be dismissed easily by an x
|
||||
class PopUpScreen : public Base {
|
||||
public:
|
||||
PopUpScreen(UI::Page::Base::Ptr aPage);
|
||||
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
private:
|
||||
UI::Page::Base *mContentPage = nullptr;
|
||||
Widget::Button *mExitButton = nullptr;
|
||||
Widget::Label *mTitle = nullptr;
|
||||
};
|
||||
|
||||
} // namespace UI::Screen
|
26
Platformio/OmoteUI/core/screen/ScreenBase.cpp
Normal file
26
Platformio/OmoteUI/core/screen/ScreenBase.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "ScreenBase.hpp"
|
||||
|
||||
using namespace UI::Screen;
|
||||
|
||||
Base::Base(ID aId) : UIElement(lv_obj_create(NULL), aId) {}
|
||||
|
||||
void Base::Show() {
|
||||
lv_scr_load_anim(LvglSelf(), mPushAnimation, mTransitionAnimationTime,
|
||||
mTransitionDelayTime, false);
|
||||
UIElement::OnShow();
|
||||
}
|
||||
|
||||
void Base::SetPushAnimation(lv_scr_load_anim_t aShowAnimation) {
|
||||
mPushAnimation = aShowAnimation;
|
||||
}
|
||||
|
||||
uint32_t Base::GetTransitionTime() {
|
||||
return mTransitionAnimationTime + mTransitionDelayTime;
|
||||
}
|
||||
|
||||
void Base::SetTransitionTimes(uint32_t aAnimationTime, uint32_t aDelay) {
|
||||
mTransitionAnimationTime = aAnimationTime;
|
||||
mTransitionDelayTime = aDelay;
|
||||
}
|
||||
|
||||
bool Base::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };
|
35
Platformio/OmoteUI/core/screen/ScreenBase.hpp
Normal file
35
Platformio/OmoteUI/core/screen/ScreenBase.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
#include "UIElement.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace UI::Screen {
|
||||
class Manager;
|
||||
|
||||
class Base : public UIElement {
|
||||
friend Manager;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<Base> Ptr;
|
||||
|
||||
Base(ID aId);
|
||||
|
||||
void SetPushAnimation(lv_scr_load_anim_t aPushAnimation);
|
||||
|
||||
uint32_t GetTransitionTime();
|
||||
void SetTransitionTimes(uint32_t aAnimationTime, uint32_t aDelay = 0);
|
||||
|
||||
protected:
|
||||
void Show() override;
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
|
||||
|
||||
private:
|
||||
lv_scr_load_anim_t mPushAnimation = LV_SCR_LOAD_ANIM_NONE;
|
||||
uint32_t mTransitionAnimationTime = 1000; // 1000 ms / 1 sec
|
||||
uint32_t mTransitionDelayTime = 0;
|
||||
};
|
||||
|
||||
} // namespace UI::Screen
|
14
Platformio/OmoteUI/core/widget/Button.cpp
Normal file
14
Platformio/OmoteUI/core/widget/Button.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "Button.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
|
||||
using namespace UI::Widget;
|
||||
|
||||
Button::Button(std::function<void()> aOnPressHandler)
|
||||
: Base(lv_btn_create(UI::Screen::BackgroundScreen::getLvInstance()),ID::Widgets::Button),
|
||||
mOnPress(aOnPressHandler) {}
|
||||
|
||||
void Button::OnLvglEvent(lv_event_t *anEvent) {
|
||||
if (anEvent->code == LV_EVENT_PRESSED) {
|
||||
mOnPress();
|
||||
}
|
||||
};
|
15
Platformio/OmoteUI/core/widget/Button.hpp
Normal file
15
Platformio/OmoteUI/core/widget/Button.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "WidgetBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class Button : public Base {
|
||||
public:
|
||||
Button(std::function<void()> aOnPressHandler);
|
||||
|
||||
void OnLvglEvent(lv_event_t *anEvent) override;
|
||||
|
||||
private:
|
||||
std::function<void()> mOnPress;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
47
Platformio/OmoteUI/core/widget/DropDown.hpp
Normal file
47
Platformio/OmoteUI/core/widget/DropDown.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include "WidgetBase.hpp"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace UI::Widget {
|
||||
|
||||
template <typename T> class DropDown : public Base {
|
||||
public:
|
||||
DropDown(std::function<void(T)> aOnItemSelected)
|
||||
: Base(lv_dropdown_create(UI::Screen::BackgroundScreen::getLvInstance()),
|
||||
ID::Widgets::DropDown),
|
||||
mSelectionHandler(aOnItemSelected) {
|
||||
lv_dropdown_clear_options(LvglSelf());
|
||||
}
|
||||
|
||||
void AddItem(std::string aOptionTitle, T aOptionData) {
|
||||
lv_dropdown_add_option(LvglSelf(), aOptionTitle.c_str(),
|
||||
LV_DROPDOWN_POS_LAST);
|
||||
mOptionsData.push_back(aOptionData);
|
||||
}
|
||||
|
||||
void SetSelected(T aOptionData) {
|
||||
for (int i = 0; i < mOptionsData.size(); i++) {
|
||||
if (mOptionsData[i] == aOptionData) {
|
||||
lv_dropdown_set_selected(LvglSelf(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO Could Implement a remove Item but need to make sure
|
||||
// correct order is retained in data vector.
|
||||
|
||||
protected:
|
||||
void OnLvglEvent(lv_event_t *anEvent) override {
|
||||
if (anEvent->code == LV_EVENT_VALUE_CHANGED) {
|
||||
auto idx = lv_dropdown_get_selected(LvglSelf());
|
||||
mSelectionHandler(mOptionsData[idx]);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::function<void(T)> mSelectionHandler;
|
||||
std::vector<T> mOptionsData;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
57
Platformio/OmoteUI/core/widget/Keyboard.cpp
Normal file
57
Platformio/OmoteUI/core/widget/Keyboard.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "Keyboard.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include <cmath>
|
||||
|
||||
using namespace UI;
|
||||
using namespace UI::Widget;
|
||||
|
||||
Keyboard::Keyboard(std::function<void(std::string)> aOnUserCompletedTextEntry,
|
||||
std::string aPrompt)
|
||||
: Base(ID::Widgets::Keyboard),
|
||||
mKeyboard(AddElement<Base>(std::make_unique<Base>(
|
||||
lv_keyboard_create(LvglSelf()), ID::Widgets::INVALID_WIDGET_ID))),
|
||||
mTextArea(AddElement<Base>(std::make_unique<Base>(
|
||||
lv_textarea_create(LvglSelf()), ID::Widgets::INVALID_WIDGET_ID))),
|
||||
mOnUserCompleteTextEntry(aOnUserCompletedTextEntry) {
|
||||
lv_keyboard_set_textarea(mKeyboard->LvglSelf(), mTextArea->LvglSelf());
|
||||
if (!aPrompt.empty()) {
|
||||
lv_textarea_set_placeholder_text(mTextArea->LvglSelf(), aPrompt.c_str());
|
||||
}
|
||||
|
||||
mKeyboard->OnLvglEvent([this](auto aEvent) {
|
||||
if (aEvent->code == LV_EVENT_READY) {
|
||||
std::string userEnteredText =
|
||||
std::string(lv_textarea_get_text(mTextArea->LvglSelf()));
|
||||
mOnUserCompleteTextEntry(userEnteredText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Keyboard::OnAdded(UIElement *aNewParent) {
|
||||
auto selfHeight = ceil(aNewParent->GetContentHeight() * 0.60f);
|
||||
// Align to final position and get Y for end of animation
|
||||
SetHeight(selfHeight);
|
||||
AlignTo(aNewParent, LV_ALIGN_BOTTOM_MID);
|
||||
auto endAnimationY = GetY();
|
||||
auto startAnimationY = aNewParent->GetBottom();
|
||||
|
||||
mAnimateIn = std::make_unique<Animation>([this](auto aY) { SetY(aY); }, 500,
|
||||
startAnimationY, endAnimationY);
|
||||
mAnimateIn->Start();
|
||||
}
|
||||
|
||||
void Keyboard::AnimateOut() {
|
||||
if (mOnKeyboardAnimatedOut) {
|
||||
mAnimateIn->HandleAnimationComplete(mOnKeyboardAnimatedOut);
|
||||
}
|
||||
mAnimateIn->Reverse();
|
||||
};
|
||||
|
||||
void Keyboard::SetHeight(lv_coord_t aHeight) {
|
||||
Base::SetHeight(aHeight);
|
||||
auto txtAreaHight = 33;
|
||||
mTextArea->SetHeight(txtAreaHight);
|
||||
mKeyboard->SetHeight(GetContentHeight() - txtAreaHight);
|
||||
mTextArea->AlignTo(this, LV_ALIGN_TOP_MID);
|
||||
mKeyboard->AlignTo(mTextArea, LV_ALIGN_OUT_BOTTOM_MID);
|
||||
}
|
32
Platformio/OmoteUI/core/widget/Keyboard.hpp
Normal file
32
Platformio/OmoteUI/core/widget/Keyboard.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include "Animation.hpp"
|
||||
#include "WidgetBase.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace UI::Widget {
|
||||
|
||||
class Keyboard : public Base {
|
||||
public:
|
||||
Keyboard(std::function<void(std::string)> aOnUserCompletedTextEntry,
|
||||
std::string aPrompt = "");
|
||||
|
||||
void OnAdded(UIElement *aNewParent) override;
|
||||
|
||||
void SetHeight(lv_coord_t aHeight) override;
|
||||
|
||||
void AnimateOut();
|
||||
void OnKeyboardAnimatedOut(std::function<void()> aOnKeyboardAnimatedOut) {
|
||||
mOnKeyboardAnimatedOut = aOnKeyboardAnimatedOut;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> mOnKeyboardAnimatedOut;
|
||||
std::function<void(std::string)> mOnUserCompleteTextEntry;
|
||||
std::unique_ptr<Animation> mAnimateIn;
|
||||
|
||||
Base *mKeyboard;
|
||||
Base *mTextArea;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
22
Platformio/OmoteUI/core/widget/Label.cpp
Normal file
22
Platformio/OmoteUI/core/widget/Label.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "Label.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
|
||||
using namespace UI::Widget;
|
||||
|
||||
Label::Label(std::string aText)
|
||||
: Base(lv_label_create(UI::Screen::BackgroundScreen::getLvInstance()),
|
||||
ID::Widgets::Label) {
|
||||
SetText(aText);
|
||||
}
|
||||
|
||||
void Label::SetText(std::string aText) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_label_set_text(LvglSelf(), aText.c_str());
|
||||
}
|
||||
|
||||
void Label::SetLongMode(lv_label_long_mode_t aLongMode) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_label_set_long_mode(LvglSelf(), aLongMode);
|
||||
}
|
16
Platformio/OmoteUI/core/widget/Label.hpp
Normal file
16
Platformio/OmoteUI/core/widget/Label.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include "WidgetBase.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace UI::Widget {
|
||||
class Label : public Base {
|
||||
public:
|
||||
Label(std::string aText);
|
||||
|
||||
void SetText(std::string aText);
|
||||
|
||||
void SetLongMode(lv_label_long_mode_t aLongMode);
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
34
Platformio/OmoteUI/core/widget/List.cpp
Normal file
34
Platformio/OmoteUI/core/widget/List.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "List.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
using namespace UI;
|
||||
using namespace UI::Widget;
|
||||
|
||||
ListItem::ListItem(lv_obj_t *aListItem, std::function<void()> onItemSelected)
|
||||
: UIElement(aListItem, ID()), mSelectedHandler(std::move(onItemSelected)) {}
|
||||
|
||||
void ListItem::OnLvglEvent(lv_event_t *anEvent) {
|
||||
if (anEvent->code == LV_EVENT_CLICKED) {
|
||||
if (mSelectedHandler) {
|
||||
mSelectedHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List::List()
|
||||
: Base(lv_list_create(Screen::BackgroundScreen::getLvInstance()),
|
||||
ID::Widgets::List) {
|
||||
StopLvglEventHandler();
|
||||
}
|
||||
|
||||
void List::AddItem(std::string aTitle, const char *aSymbol,
|
||||
std::function<void()> onItemSelected) {
|
||||
lv_obj_t *lvListItem = nullptr;
|
||||
{
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lvListItem = lv_list_add_btn(LvglSelf(), aSymbol, aTitle.c_str());
|
||||
}
|
||||
mListItems.push_back(
|
||||
std::make_unique<ListItem>(lvListItem, std::move(onItemSelected)));
|
||||
mListItems.back()->SetHeight(lv_pct(20));
|
||||
}
|
32
Platformio/OmoteUI/core/widget/List.hpp
Normal file
32
Platformio/OmoteUI/core/widget/List.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include "WidgetBase.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace UI::Widget {
|
||||
|
||||
class ListItem : public UIElement {
|
||||
public:
|
||||
ListItem(lv_obj_t *aListItem, std::function<void()> onItemSelected);
|
||||
|
||||
protected:
|
||||
void OnLvglEvent(lv_event_t *anEvent) override;
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent anEvent) override {
|
||||
return false;
|
||||
};
|
||||
|
||||
private:
|
||||
std::function<void()> mSelectedHandler;
|
||||
};
|
||||
|
||||
class List : public Base {
|
||||
public:
|
||||
List();
|
||||
void AddItem(std::string aTitle, const char *aSymbol,
|
||||
std::function<void()> onItemSelected);
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::vector<UIElement::Ptr> mListItems;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
31
Platformio/OmoteUI/core/widget/Slider.cpp
Normal file
31
Platformio/OmoteUI/core/widget/Slider.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "Slider.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
#include "LvglResourceManager.hpp"
|
||||
|
||||
using namespace UI::Widget;
|
||||
|
||||
Slider::Slider(std::function<void(int32_t)> aOnSliderValueChange,
|
||||
int32_t aMinVal, int32_t aMaxVal)
|
||||
: Base(lv_slider_create(UI::Screen::BackgroundScreen::getLvInstance()),
|
||||
ID::Widgets::Slider),
|
||||
mOnSliderChange(std::move(aOnSliderValueChange)) {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
lv_slider_set_range(LvglSelf(), aMinVal, aMaxVal);
|
||||
}
|
||||
|
||||
int32_t Slider::GetValue() {
|
||||
auto lock = LvglResourceManager::GetInstance().scopeLock();
|
||||
return lv_slider_get_value(LvglSelf());
|
||||
}
|
||||
|
||||
void Slider::SetValue(int32_t aValue, lv_anim_enable_t aIsAnimate) {
|
||||
LvglResourceManager::GetInstance().AttemptNow([this, aValue, aIsAnimate] {
|
||||
lv_slider_set_value(LvglSelf(), aValue, aIsAnimate);
|
||||
});
|
||||
}
|
||||
|
||||
void Slider::OnLvglEvent(lv_event_t *anEvent) {
|
||||
if (anEvent->code == LV_EVENT_VALUE_CHANGED) {
|
||||
mOnSliderChange(GetValue());
|
||||
}
|
||||
}
|
19
Platformio/OmoteUI/core/widget/Slider.hpp
Normal file
19
Platformio/OmoteUI/core/widget/Slider.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "WidgetBase.hpp"
|
||||
|
||||
namespace UI::Widget {
|
||||
class Slider : public Base {
|
||||
public:
|
||||
Slider(std::function<void(int32_t)> OnSliderValueChange, int32_t aMinVal = 0,
|
||||
int32_t aMaxVal = 100);
|
||||
|
||||
int32_t GetValue();
|
||||
void SetValue(int32_t aValue, lv_anim_enable_t aIsAnimate = LV_ANIM_ON);
|
||||
|
||||
protected:
|
||||
void OnLvglEvent(lv_event_t *anEvent) override;
|
||||
|
||||
private:
|
||||
std::function<void(int32_t)> mOnSliderChange;
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
23
Platformio/OmoteUI/core/widget/WidgetBase.cpp
Normal file
23
Platformio/OmoteUI/core/widget/WidgetBase.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "WidgetBase.hpp"
|
||||
#include "BackgroundScreen.hpp"
|
||||
|
||||
using namespace UI;
|
||||
using namespace UI::Widget;
|
||||
|
||||
// Constructor typically used as a container for other widgets
|
||||
Base::Base(ID anId)
|
||||
: UIElement(lv_obj_create(Screen::BackgroundScreen::getLvInstance()),
|
||||
anId) {
|
||||
SetWidth(lv_pct(100));
|
||||
SetHeight(lv_pct(100));
|
||||
SetPadding(Padding());
|
||||
SetOutline(Outline());
|
||||
SetBorder(Border());
|
||||
SetBgOpacity(LV_OPA_TRANSP);
|
||||
}
|
||||
|
||||
Base::Base(lv_obj_t *aLvglSelf, ID anId) : UIElement(aLvglSelf, anId) {
|
||||
SetWidth(lv_pct(100));
|
||||
SetHeight(lv_pct(100));
|
||||
SetBorder(Border());
|
||||
}
|
34
Platformio/OmoteUI/core/widget/WidgetBase.hpp
Normal file
34
Platformio/OmoteUI/core/widget/WidgetBase.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "UIElement.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace UI {
|
||||
|
||||
namespace Screen {
|
||||
class PopUpScreen;
|
||||
}
|
||||
} // namespace UI
|
||||
|
||||
namespace UI::Widget {
|
||||
|
||||
class Base : public UIElement {
|
||||
// Classes that Own Widgets
|
||||
friend class UI::Screen::PopUpScreen;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<Base> Ptr;
|
||||
|
||||
Base(ID anId);
|
||||
Base(lv_obj_t *aLvglSelf, ID anId);
|
||||
virtual ~Base() override = default;
|
||||
|
||||
protected:
|
||||
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override {
|
||||
return false;
|
||||
};
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace UI::Widget
|
|
@ -1,26 +0,0 @@
|
|||
#include "poller.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
poller::poller(std::function<void()> aOnPollCb, milliseconds aPollTime):mIntermittentCallback(std::move(aOnPollCb)){
|
||||
mTimer = lv_timer_create(poller::onPoll,aPollTime.count(),this);
|
||||
lv_timer_set_repeat_count(mTimer,-1); // Call forever
|
||||
}
|
||||
|
||||
poller::~poller(){
|
||||
if(mTimer){
|
||||
lv_timer_del(mTimer);
|
||||
mTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void poller::onPoll(_lv_timer_t* aTimer){
|
||||
poller* currentPoller = reinterpret_cast<poller*>(aTimer->user_data);
|
||||
|
||||
if(currentPoller->mIntermittentCallback){
|
||||
currentPoller->mIntermittentCallback();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "lvgl.h"
|
||||
|
||||
class poller{
|
||||
public:
|
||||
poller(std::function<void()> aOnPollCb, std::chrono::milliseconds pollTime = std::chrono::seconds(5));
|
||||
virtual ~poller();
|
||||
|
||||
void setPollPeriod(std::chrono::milliseconds aPollPeriod){ lv_timer_set_period(mTimer, aPollPeriod.count());}
|
||||
inline void pause() { lv_timer_pause(mTimer);}
|
||||
inline void resume() { lv_timer_resume(mTimer);}
|
||||
inline void reset() { lv_timer_reset(mTimer);}
|
||||
inline void runNext() { lv_timer_ready(mTimer);}
|
||||
|
||||
private:
|
||||
lv_timer_t* mTimer = nullptr;
|
||||
std::function<void()> mIntermittentCallback = nullptr;
|
||||
|
||||
// Static function registered to every timers callback to pass this object as context
|
||||
static void onPoll(_lv_timer_t* aTimer);
|
||||
};
|
|
@ -22,7 +22,7 @@ build_flags =
|
|||
-D LV_CONF_SKIP
|
||||
;------------- LVGL ------------------------------------------
|
||||
-D LV_MEM_CUSTOM=1
|
||||
-D LV_MEM_SIZE="\(48U * 1024U\)"
|
||||
-D LV_MEM_SIZE="(48U * 1024U)"
|
||||
-D LV_FONT_MONTSERRAT_12=1
|
||||
-D LV_FONT_MONTSERRAT_16=1
|
||||
-D LV_FONT_MONTSERRAT_24=1
|
||||
|
@ -39,6 +39,16 @@ build_flags =
|
|||
|
||||
; ------------- Includes ------------------------------------
|
||||
-I OmoteUI
|
||||
-I OmoteUI/core
|
||||
-I OmoteUI/core/screen
|
||||
-I OmoteUI/core/widget
|
||||
-I OmoteUI/core/page
|
||||
-I OmoteUI/UIs
|
||||
;-I OmoteUI/UIs/Basic
|
||||
-I OmoteUI/UIs/BasicRefactored
|
||||
-I OmoteUI/UIs/BasicRefactored/screen
|
||||
-I OmoteUI/UIs/BasicRefactored/page
|
||||
-I OmoteUI/UIs/BasicRefactored/widget
|
||||
-I HAL
|
||||
-I HAL/HardwareModules
|
||||
|
||||
|
@ -49,7 +59,8 @@ lib_deps =
|
|||
lib_archive = false
|
||||
build_src_filter =
|
||||
+<../OmoteUI/*>
|
||||
+<../HAL/HardwareAbstract.cpp>
|
||||
-<../OmoteUI/UIs/Basic/*>
|
||||
+<../HAL/*.cpp>
|
||||
+<../HAL/HardwareModules/*.cpp>
|
||||
|
||||
|
||||
|
@ -77,6 +88,7 @@ lib_deps =
|
|||
Preferences
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D OMOTE_ESP32
|
||||
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
|
||||
|
@ -97,12 +109,15 @@ build_flags =
|
|||
-D LV_TICK_CUSTOM=1
|
||||
-D LV_TICK_CUSTOM_INCLUDE="\"Arduino.h\""
|
||||
-D LV_TICK_CUSTOM_SYS_TIME_EXPR="'(millis())'"
|
||||
|
||||
|
||||
; ------------- Includes --------------------------------------------
|
||||
-I HAL/Targets/ESP32
|
||||
-I HAL/Targets/ESP32/battery
|
||||
-I HAL/Targets/ESP32/display
|
||||
-I HAL/Targets/ESP32/wifiHandler
|
||||
-I HAL/Targets/ESP32/keys
|
||||
|
||||
monitor_filters = esp32_exception_decoder
|
||||
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
|
@ -116,15 +131,16 @@ build_src_filter =
|
|||
platform = native@^1.1.3
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
|
||||
-D OMOTE_SIM
|
||||
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_INFO
|
||||
;-D LV_LOG_PRINTF=1
|
||||
-lSDL2 ; SDL2 must be installed on system! Windows:msys2 ubuntu:apt-get
|
||||
-lpthread ; std::thread for Linux
|
||||
; --------- SDL drivers options -----------------------------
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_DRV_NO_CONF
|
||||
-D USE_SDL
|
||||
-D SDL_MAIN_HANDLED
|
||||
-D SDL_MAIN_HANDLED
|
||||
-D SDL_HOR_RES=SCREEN_WIDTH
|
||||
-D SDL_VER_RES=SCREEN_HEIGHT
|
||||
-D SDL_ZOOM=1
|
||||
|
@ -136,6 +152,7 @@ build_flags =
|
|||
|
||||
debug_build_flags =
|
||||
-g ;Allow debugging in vscode
|
||||
-O0 ;No Optomizations
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
|
|
18
Platformio/src/OmoteSetup.hpp
Normal file
18
Platformio/src/OmoteSetup.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "BasicUI.hpp"
|
||||
#include "HardwareFactory.hpp"
|
||||
|
||||
namespace OMOTE {
|
||||
std::shared_ptr<UI::UIBase> ui = nullptr;
|
||||
|
||||
void setup() {
|
||||
HardwareFactory::getAbstract().init();
|
||||
ui = std::make_unique<UI::BasicUI>();
|
||||
lv_timer_handler(); // Run the LVGL UI once before the loop takes over
|
||||
}
|
||||
|
||||
void loop() {
|
||||
HardwareFactory::getAbstract().loopHandler();
|
||||
ui->loopHandler();
|
||||
}
|
||||
|
||||
} // namespace OMOTE
|
|
@ -1,24 +1,6 @@
|
|||
// OMOTE firmware for ESP32
|
||||
// 2023 Maximilian Kern
|
||||
|
||||
#include <lvgl.h>
|
||||
#include "HardwareRevX.hpp"
|
||||
#include "OmoteUI.hpp"
|
||||
#include "omoteconfig.h"
|
||||
|
||||
std::shared_ptr<HardwareRevX> hal = nullptr;
|
||||
|
||||
void setup() {
|
||||
hal = HardwareRevX::getInstance();
|
||||
hal->init();
|
||||
|
||||
auto ui = OmoteUI::getInstance(hal);
|
||||
ui->layout_UI();
|
||||
|
||||
lv_timer_handler(); // Run the LVGL UI once before the loop takes over
|
||||
}
|
||||
|
||||
void loop() {
|
||||
HardwareRevX::getInstance()->loopHandler();
|
||||
OmoteUI::getInstance()->loopHandler();
|
||||
}
|
||||
#include "OmoteSetup.hpp"
|
||||
void setup() { OMOTE::setup(); }
|
||||
void loop() { OMOTE::loop(); }
|
|
@ -1,17 +1,8 @@
|
|||
#include "HardwareSimulator.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include "OmoteUI.hpp"
|
||||
#include <memory>
|
||||
#include "OmoteSetup.hpp"
|
||||
|
||||
int main(){
|
||||
auto hwSim = std::make_shared<HardwareSimulator>();
|
||||
hwSim->init();
|
||||
|
||||
auto ui = OmoteUI::getInstance(hwSim);
|
||||
ui->layout_UI();
|
||||
|
||||
while (true){
|
||||
ui->loopHandler();
|
||||
lv_task_handler();
|
||||
}
|
||||
int main() {
|
||||
OMOTE::setup();
|
||||
while (true) {
|
||||
OMOTE::loop();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue