From 5731148bf62ca0f9f7380ec3c07befc2b5b5b50b Mon Sep 17 00:00:00 2001 From: Matthew Colvin <35540398+Mc067415@users.noreply.github.com> Date: Sun, 13 Aug 2023 22:14:40 -0500 Subject: [PATCH] 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. --- Platformio/HAL/DisplayInterface.cpp | 35 ++++++ Platformio/HAL/HardwareAbstract.cpp | 1 + Platformio/HAL/HardwareAbstract.hpp | 2 + .../HAL/HardwareInterfaces/DisplayInterface.h | 18 ++- Platformio/HAL/Targets/ESP32/HardwareRevX.cpp | 84 +------------ Platformio/HAL/Targets/ESP32/HardwareRevX.hpp | 32 +---- .../HAL/Targets/ESP32/display/display.cpp | 114 ++++++++++++------ .../HAL/Targets/ESP32/display/display.hpp | 28 +++-- .../Targets/Simulator/HardwareSimulator.cpp | 2 - Platformio/platformio.ini | 1 + 10 files changed, 154 insertions(+), 163 deletions(-) create mode 100644 Platformio/HAL/DisplayInterface.cpp diff --git a/Platformio/HAL/DisplayInterface.cpp b/Platformio/HAL/DisplayInterface.cpp new file mode 100644 index 0000000..572ec63 --- /dev/null +++ b/Platformio/HAL/DisplayInterface.cpp @@ -0,0 +1,35 @@ +#include "DisplayInterface.h" + +std::shared_ptr 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); +} \ No newline at end of file diff --git a/Platformio/HAL/HardwareAbstract.cpp b/Platformio/HAL/HardwareAbstract.cpp index e4fae8c..91f1e89 100644 --- a/Platformio/HAL/HardwareAbstract.cpp +++ b/Platformio/HAL/HardwareAbstract.cpp @@ -10,6 +10,7 @@ HardwareAbstract::HardwareAbstract( mDisplay(std::move(aDisplay)) {} + std::optional HardwareAbstract::getBatteryStatus(){ if(mBattery){ HardwareAbstract::batteryStatus currentStatus; diff --git a/Platformio/HAL/HardwareAbstract.hpp b/Platformio/HAL/HardwareAbstract.hpp index f3c91c9..8b62800 100644 --- a/Platformio/HAL/HardwareAbstract.hpp +++ b/Platformio/HAL/HardwareAbstract.hpp @@ -48,4 +48,6 @@ public: std::shared_ptr mBattery; std::shared_ptr mWifiHandler; std::shared_ptr mDisplay; + + }; diff --git a/Platformio/HAL/HardwareInterfaces/DisplayInterface.h b/Platformio/HAL/HardwareInterfaces/DisplayInterface.h index 5080f8e..62e3a5b 100644 --- a/Platformio/HAL/HardwareInterfaces/DisplayInterface.h +++ b/Platformio/HAL/HardwareInterfaces/DisplayInterface.h @@ -1,13 +1,27 @@ #pragma once -#include +#include #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 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]; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp b/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp index 909f937..8351908 100644 --- a/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp +++ b/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp @@ -55,7 +55,7 @@ HardwareRevX::HardwareRevX(): HardwareAbstract( std::make_shared(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::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 diff --git a/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp b/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp index f014289..cfd9bc9 100644 --- a/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp +++ b/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp @@ -2,10 +2,8 @@ #include "SparkFunLIS3DH.h" #include "HardwareAbstract.hpp" -#include "Wire.h" #include "lvgl.h" #include "battery.hpp" -#include #include #include #include @@ -13,7 +11,6 @@ #include // modified for inverted logic #include #include -#include // Hardware-specific library #include #include @@ -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 diff --git a/Platformio/HAL/Targets/ESP32/display/display.cpp b/Platformio/HAL/Targets/ESP32/display/display.cpp index 8ef3097..e9566c3 100644 --- a/Platformio/HAL/Targets/ESP32/display/display.cpp +++ b/Platformio/HAL/Targets/ESP32/display/display.cpp @@ -1,56 +1,58 @@ #include "display.hpp" #include "omoteconfig.h" +#include "Wire.h" -std::shared_ptr Display::mInstance = nullptr; - -std::shared_ptr Display::getInstance() +std::shared_ptr Display::getInstance(int& standby_timer) { - if (mInstance == nullptr) + if (DisplayInterface::mInstance == nullptr) { - mInstance = std::shared_ptr(new Display(LCD_EN, LCD_BL)); + DisplayInterface::mInstance = std::shared_ptr(new Display(LCD_EN, LCD_BL, standby_timer)); } - - return mInstance; + return std::static_pointer_cast(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); +} \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/display/display.hpp b/Platformio/HAL/Targets/ESP32/display/display.hpp index 7baa25c..2e9e0b2 100644 --- a/Platformio/HAL/Targets/ESP32/display/display.hpp +++ b/Platformio/HAL/Targets/ESP32/display/display.hpp @@ -1,7 +1,8 @@ #pragma once #include "DisplayInterface.h" -#include +#include #include +#include #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 getInstance(); + static std::shared_ptr 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 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; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp index 27f64a2..3e9ea0e 100644 --- a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp +++ b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp @@ -25,8 +25,6 @@ static int tick_thread(void * data) } - - void HardwareSimulator::init() { lv_init(); // Workaround for sdl2 `-m32` crash diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index fdd19ea..a58d404 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -48,6 +48,7 @@ lib_archive = false build_src_filter = +<../OmoteUI/*> +<../HAL/HardwareAbstract.cpp> + +<../HAL/DisplayInterface.cpp>