Turn Display Interface into a singleton Abstract class that can do the registration of callbacks to LVGL and allow implementers of the abstract to support LVGL.
This commit is contained in:
parent
419ac45e98
commit
5731148bf6
10 changed files with 154 additions and 163 deletions
35
Platformio/HAL/DisplayInterface.cpp
Normal file
35
Platformio/HAL/DisplayInterface.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "DisplayInterface.h"
|
||||
|
||||
std::shared_ptr<DisplayInterface> DisplayInterface::mInstance = nullptr;
|
||||
|
||||
DisplayInterface::DisplayInterface(){
|
||||
lv_init();
|
||||
|
||||
lv_disp_draw_buf_init(&mdraw_buf, mbufA, mbufB,
|
||||
SCREEN_WIDTH * SCREEN_HEIGHT / 10);
|
||||
|
||||
// Initialize the display driver
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = SCREEN_WIDTH;
|
||||
disp_drv.ver_res = SCREEN_HEIGHT;
|
||||
disp_drv.flush_cb = &DisplayInterface::flushDisplayImpl;
|
||||
disp_drv.draw_buf = &mdraw_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
// Initialize the touchscreen driver
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = &DisplayInterface::screenInputImpl;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
|
||||
}
|
||||
|
||||
void DisplayInterface::flushDisplayImpl(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
|
||||
mInstance->flushDisplay(disp, area, color_p);
|
||||
}
|
||||
|
||||
void DisplayInterface::screenInputImpl(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
|
||||
mInstance->screenInput(indev_driver, data);
|
||||
}
|
|
@ -10,6 +10,7 @@ HardwareAbstract::HardwareAbstract(
|
|||
mDisplay(std::move(aDisplay))
|
||||
{}
|
||||
|
||||
|
||||
std::optional<HardwareAbstract::batteryStatus> HardwareAbstract::getBatteryStatus(){
|
||||
if(mBattery){
|
||||
HardwareAbstract::batteryStatus currentStatus;
|
||||
|
|
|
@ -48,4 +48,6 @@ public:
|
|||
std::shared_ptr<BatteryInterface> mBattery;
|
||||
std::shared_ptr<wifiHandlerInterface> mWifiHandler;
|
||||
std::shared_ptr<DisplayInterface> mDisplay;
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -1,13 +1,27 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "lvgl.h"
|
||||
class DisplayInterface
|
||||
{
|
||||
public:
|
||||
DisplayInterface();
|
||||
virtual void setBrightness(uint8_t brightness) = 0;
|
||||
virtual void turnOff() = 0;
|
||||
|
||||
protected:
|
||||
virtual void pushPixel(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t* pixel_values) = 0;
|
||||
// Set this with a getInstance method in the Child Class
|
||||
static std::shared_ptr<DisplayInterface> mInstance;
|
||||
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) = 0;
|
||||
virtual void screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) = 0;
|
||||
private:
|
||||
|
||||
// Used to satisfy LVGL APIs
|
||||
static void flushDisplayImpl(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
|
||||
static void screenInputImpl(lv_indev_drv_t *indev_driver, lv_indev_data_t *data);
|
||||
|
||||
// LVGL Screen Buffers
|
||||
lv_disp_draw_buf_t mdraw_buf;
|
||||
lv_color_t mbufA[SCREEN_WIDTH * SCREEN_HEIGHT / 10];
|
||||
lv_color_t mbufB[SCREEN_WIDTH * SCREEN_HEIGHT / 10];
|
||||
};
|
|
@ -55,7 +55,7 @@ HardwareRevX::HardwareRevX():
|
|||
HardwareAbstract(
|
||||
std::make_shared<Battery>(ADC_BAT,CRG_STAT),
|
||||
wifiHandler::getInstance(),
|
||||
Display::getInstance()
|
||||
Display::getInstance(standbyTimer)
|
||||
){}
|
||||
|
||||
HardwareRevX::WakeReason getWakeReason() {
|
||||
|
@ -80,9 +80,6 @@ void HardwareRevX::init() {
|
|||
Serial.begin(115200);
|
||||
restorePreferences();
|
||||
slowDisplayWakeup();
|
||||
setupTFT();
|
||||
setupTouchScreen();
|
||||
initLVGL();
|
||||
setupIMU();
|
||||
setupIR();
|
||||
|
||||
|
@ -100,72 +97,6 @@ std::shared_ptr<HardwareRevX> HardwareRevX::getInstance(){
|
|||
return mInstance;
|
||||
}
|
||||
|
||||
void HardwareRevX::initLVGL() {
|
||||
lv_init();
|
||||
|
||||
lv_disp_draw_buf_init(&mdraw_buf, mbufA, mbufB,
|
||||
SCREEN_WIDTH * SCREEN_HEIGHT / 10);
|
||||
|
||||
// Initialize the display driver
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = SCREEN_WIDTH;
|
||||
disp_drv.ver_res = SCREEN_HEIGHT;
|
||||
disp_drv.flush_cb = &HardwareRevX::displayFlushImpl;
|
||||
disp_drv.draw_buf = &mdraw_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
// Initialize the touchscreen driver
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = &HardwareRevX::touchPadReadImpl;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
}
|
||||
|
||||
void HardwareRevX::handleDisplayFlush(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);
|
||||
|
||||
tft.startWrite();
|
||||
tft.setAddrWindow(area->x1, area->y1, w, h);
|
||||
tft.pushPixelsDMA((uint16_t *)&color_p->full, w * h);
|
||||
tft.endWrite();
|
||||
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
void HardwareRevX::handleTouchPadRead(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;
|
||||
standbyTimer = SLEEP_TIMEOUT;
|
||||
}
|
||||
|
||||
if (!touched) {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
|
||||
// Set the coordinates
|
||||
data->point.x = SCREEN_WIDTH - touchX;
|
||||
data->point.y = SCREEN_HEIGHT - touchY;
|
||||
|
||||
// Serial.print( "touchpoint: x" );
|
||||
// Serial.print( touchX );
|
||||
// Serial.print( " y" );
|
||||
// Serial.println( touchY );
|
||||
// tft.drawFastHLine(0, screenHeight - touchY, screenWidth, TFT_RED);
|
||||
// tft.drawFastVLine(screenWidth - touchX, 0, screenHeight, TFT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
void HardwareRevX::activityDetection() {
|
||||
static int accXold;
|
||||
|
@ -332,20 +263,7 @@ void HardwareRevX::restorePreferences() {
|
|||
}
|
||||
}
|
||||
|
||||
void HardwareRevX::setupTFT() {
|
||||
// Setup TFT
|
||||
tft.init();
|
||||
tft.initDMA();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setSwapBytes(true);
|
||||
}
|
||||
|
||||
void HardwareRevX::setupTouchScreen() {
|
||||
// Configure i2c pins and set frequency to 400kHz
|
||||
Wire.begin(SDA, SCL, 400000);
|
||||
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
}
|
||||
|
||||
void HardwareRevX::setupIMU() {
|
||||
// Setup hal
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
#include "SparkFunLIS3DH.h"
|
||||
|
||||
#include "HardwareAbstract.hpp"
|
||||
#include "Wire.h"
|
||||
#include "lvgl.h"
|
||||
#include "battery.hpp"
|
||||
#include <Adafruit_FT6206.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRsend.h>
|
||||
|
@ -13,7 +11,6 @@
|
|||
#include <Keypad.h> // modified for inverted logic
|
||||
#include <Preferences.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
|
@ -39,9 +36,6 @@ protected:
|
|||
void setupBacklight();
|
||||
void restorePreferences();
|
||||
void slowDisplayWakeup();
|
||||
void setupTFT();
|
||||
void setupTouchScreen();
|
||||
void initLVGL();
|
||||
void setupIMU();
|
||||
void setupIR();
|
||||
|
||||
|
@ -49,11 +43,6 @@ protected:
|
|||
void enterSleep();
|
||||
void configIMUInterrupts();
|
||||
|
||||
// UI/UX Handlers
|
||||
void handleDisplayFlush(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p);
|
||||
void handleTouchPadRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data);
|
||||
|
||||
// Tasks
|
||||
void startTasks();
|
||||
/// @brief Send Battery Notification every 5 Seconds
|
||||
|
@ -64,22 +53,6 @@ protected:
|
|||
private:
|
||||
HardwareRevX();
|
||||
|
||||
// Static Wrappers Needed to Satisfy C APIs
|
||||
static void displayFlushImpl(lv_disp_drv_t *disp, const lv_area_t *area,
|
||||
lv_color_t *color_p) {
|
||||
mInstance->handleDisplayFlush(disp, area, color_p);
|
||||
}
|
||||
static void touchPadReadImpl(lv_indev_drv_t *indev_driver,
|
||||
lv_indev_data_t *data) {
|
||||
mInstance->handleTouchPadRead(indev_driver, data);
|
||||
}
|
||||
|
||||
Adafruit_FT6206 touch = Adafruit_FT6206();
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
// IMU Motion Detection
|
||||
LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
|
||||
int standbyTimer = SLEEP_TIMEOUT;
|
||||
|
@ -96,10 +69,7 @@ private:
|
|||
IRsend IrSender = IRsend(IR_LED, true);
|
||||
IRrecv IrReceiver = IRrecv(IR_RX);
|
||||
|
||||
// LVGL Screen Buffers
|
||||
lv_disp_draw_buf_t mdraw_buf;
|
||||
lv_color_t mbufA[SCREEN_WIDTH * SCREEN_HEIGHT / 10];
|
||||
lv_color_t mbufB[SCREEN_WIDTH * SCREEN_HEIGHT / 10];
|
||||
|
||||
|
||||
lv_color_t color_primary = lv_color_hex(0x303030); // gray
|
||||
|
||||
|
|
|
@ -1,56 +1,58 @@
|
|||
|
||||
#include "display.hpp"
|
||||
#include "omoteconfig.h"
|
||||
#include "Wire.h"
|
||||
|
||||
std::shared_ptr<Display> Display::mInstance = nullptr;
|
||||
|
||||
std::shared_ptr<Display> Display::getInstance()
|
||||
std::shared_ptr<Display> Display::getInstance(int& standby_timer)
|
||||
{
|
||||
if (mInstance == nullptr)
|
||||
if (DisplayInterface::mInstance == nullptr)
|
||||
{
|
||||
mInstance = std::shared_ptr<Display>(new Display(LCD_EN, LCD_BL));
|
||||
DisplayInterface::mInstance = std::shared_ptr<Display>(new Display(LCD_EN, LCD_BL, standby_timer));
|
||||
}
|
||||
|
||||
return mInstance;
|
||||
return std::static_pointer_cast<Display>(mInstance);
|
||||
}
|
||||
|
||||
Display::Display(int backlight_pin, int enable_pin)
|
||||
Display::Display(int backlight_pin, int enable_pin, int& standby_timer): DisplayInterface(),
|
||||
mBacklightPin(backlight_pin),
|
||||
mEnablePin(enable_pin),
|
||||
tft(TFT_eSPI()),
|
||||
touch(Adafruit_FT6206()),
|
||||
standbyTimer(standby_timer)
|
||||
{
|
||||
this->enable_pin = enable_pin;
|
||||
this->backlight_pin = backlight_pin;
|
||||
pinMode(this->enable_pin, OUTPUT);
|
||||
digitalWrite(this->enable_pin, HIGH);
|
||||
pinMode(this->backlight_pin, OUTPUT);
|
||||
digitalWrite(this->backlight_pin, HIGH);
|
||||
|
||||
this->tft = TFT_eSPI();
|
||||
pinMode(mEnablePin, OUTPUT);
|
||||
digitalWrite(mEnablePin, HIGH);
|
||||
pinMode(mBacklightPin, OUTPUT);
|
||||
digitalWrite(mBacklightPin, HIGH);
|
||||
|
||||
ledcSetup(LCD_BACKLIGHT_LEDC_CHANNEL, LCD_BACKLIGHT_LEDC_FREQUENCY, LCD_BACKLIGHT_LEDC_BIT_RESOLUTION);
|
||||
ledcAttachPin(this->backlight_pin, LCD_BACKLIGHT_LEDC_CHANNEL);
|
||||
ledcAttachPin(mBacklightPin, LCD_BACKLIGHT_LEDC_CHANNEL);
|
||||
ledcWrite(LCD_BACKLIGHT_LEDC_CHANNEL, 0);
|
||||
|
||||
this->tft.init();
|
||||
this->tft.initDMA();
|
||||
this->tft.setRotation(0);
|
||||
this->tft.fillScreen(TFT_BLACK);
|
||||
this->tft.setSwapBytes(true);
|
||||
setupTFT();
|
||||
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for(int i = 0; i < 100; i++){
|
||||
digitalWrite(this->enable_pin, HIGH); // LCD Logic off
|
||||
digitalWrite(this->mEnablePin, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(this->enable_pin, LOW); // LCD Logic on
|
||||
digitalWrite(this->mEnablePin, LOW); // LCD Logic on
|
||||
}
|
||||
|
||||
setupTouchScreen();
|
||||
}
|
||||
|
||||
void Display::pushPixel(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t* pixel_values)
|
||||
{
|
||||
this->tft.startWrite();
|
||||
this->tft.setAddrWindow( x, y, w, h );
|
||||
this->tft.pushPixelsDMA(pixel_values, w * h);
|
||||
this->tft.endWrite();
|
||||
void Display::setupTFT() {
|
||||
tft.init();
|
||||
tft.initDMA();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
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::setBrightness(uint8_t brigthness)
|
||||
|
@ -60,11 +62,51 @@ void Display::setBrightness(uint8_t brigthness)
|
|||
|
||||
void Display::turnOff()
|
||||
{
|
||||
digitalWrite(this->backlight_pin, HIGH);
|
||||
digitalWrite(this->enable_pin, HIGH);
|
||||
pinMode(this->backlight_pin, INPUT);
|
||||
pinMode(this->enable_pin, INPUT);
|
||||
gpio_hold_en((gpio_num_t) this->backlight_pin);
|
||||
gpio_hold_en((gpio_num_t) this->enable_pin);
|
||||
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;
|
||||
touchPoint = touch.getPoint();
|
||||
int16_t touchX = touchPoint.x;
|
||||
int16_t touchY = touchPoint.y;
|
||||
bool touched = false;
|
||||
if ((touchX > 0) || (touchY > 0)) {
|
||||
touched = true;
|
||||
standbyTimer = SLEEP_TIMEOUT;
|
||||
}
|
||||
|
||||
if (!touched) {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
|
||||
// Set the coordinates
|
||||
data->point.x = SCREEN_WIDTH - touchX;
|
||||
data->point.y = SCREEN_HEIGHT - touchY;
|
||||
|
||||
// Serial.print( "touchpoint: x" );
|
||||
// Serial.print( touchX );
|
||||
// Serial.print( " y" );
|
||||
// Serial.println( touchY );
|
||||
// tft.drawFastHLine(0, screenHeight - touchY, screenWidth, TFT_RED);
|
||||
// tft.drawFastVLine(screenWidth - touchX, 0, screenHeight, TFT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
tft.startWrite();
|
||||
tft.setAddrWindow(area->x1, area->y1, w, h);
|
||||
tft.pushPixelsDMA((uint16_t *)&color_p->full, w * h);
|
||||
tft.endWrite();
|
||||
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
#include "DisplayInterface.h"
|
||||
#include <TFT_eSPI.h>
|
||||
#include <Adafruit_FT6206.h>
|
||||
#include <memory>
|
||||
#include <TFT_eSPI.h>
|
||||
#include "driver/ledc.h"
|
||||
|
||||
/*LEDC Channel to use for the LCD backlight*/
|
||||
|
@ -17,19 +18,28 @@
|
|||
class Display: public DisplayInterface
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<Display> getInstance();
|
||||
static std::shared_ptr<Display> getInstance(int& standby_timer);
|
||||
|
||||
virtual void setBrightness(uint8_t brightness) override;
|
||||
virtual void turnOff() override;
|
||||
|
||||
protected:
|
||||
virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {};
|
||||
virtual void pushPixel(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t* pixel_values) override;
|
||||
|
||||
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:
|
||||
static std::shared_ptr<Display> mInstance;
|
||||
int enable_pin;
|
||||
int backlight_pin;
|
||||
Display(int backlight_pin, int enable_pin);
|
||||
// TODO Find a better way to handle timeout resets
|
||||
Display(int backlight_pin, int enable_pin, int& standby_timer);
|
||||
void setupTFT();
|
||||
void setupTouchScreen();
|
||||
|
||||
int mEnablePin;
|
||||
int mBacklightPin;
|
||||
TFT_eSPI tft;
|
||||
|
||||
Adafruit_FT6206 touch;
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
|
||||
int& standbyTimer;
|
||||
};
|
|
@ -25,8 +25,6 @@ static int tick_thread(void * data)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void HardwareSimulator::init() {
|
||||
lv_init();
|
||||
// Workaround for sdl2 `-m32` crash
|
||||
|
|
|
@ -48,6 +48,7 @@ lib_archive = false
|
|||
build_src_filter =
|
||||
+<../OmoteUI/*>
|
||||
+<../HAL/HardwareAbstract.cpp>
|
||||
+<../HAL/DisplayInterface.cpp>
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue