Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: LVGL driver #32

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#ifdef LGFX_DRIVER
#include "LovyanGFX.h"
#include "graphics/driver/DisplayDriverConfig.h"
#include "graphics/driver/TFTDriver.h"
Expand Down Expand Up @@ -460,3 +461,5 @@ template <class LGFX> void LGFXDriver<LGFX>::printConfig(void)
ILOG_DEBUG("BL pin assigned");
}
}

#endif
17 changes: 17 additions & 0 deletions include/graphics/LGFX/LGFX_GENERIC.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* build_flags =
* -D LGFX_DRIVER_TEMPLATE
* -D LGFX_DRIVER=LGFX_GENERIC
* -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\"
* -D LGFX_PANEL=ST7789
* -D LGFX_TOUCH=XPT2046
* -D LGFX_INVERT_COLOR=true
Expand All @@ -30,6 +31,8 @@
*/

#define LGFX_USE_V1
#include "hal/gpio_types.h"
#include "util/ILog.h"
#include <LovyanGFX.hpp>

#ifndef SPI_FREQUENCY
Expand Down Expand Up @@ -206,6 +209,20 @@ class LGFX_GENERIC : public lgfx::LGFX_Device

bool hasButton(void) { return false; }

bool init_impl(bool use_reset, bool use_clear) override
{
// increase output power to SPI GPIOs to be able to run with higher frequency
if (LGFX_PIN_SCK >= 0) {
gpio_set_direction((gpio_num_t)LGFX_PIN_SCK, GPIO_MODE_OUTPUT);
gpio_set_drive_capability((gpio_num_t)LGFX_PIN_SCK, GPIO_DRIVE_CAP_3);
}
if (LGFX_PIN_MOSI >= 0) {
gpio_set_direction((gpio_num_t)LGFX_PIN_SCK, GPIO_MODE_OUTPUT);
gpio_set_drive_capability((gpio_num_t)LGFX_PIN_MOSI, GPIO_DRIVE_CAP_3);
}
return lgfx::LGFX_Device::init_impl(use_reset, use_clear);
}

LGFX_GENERIC(void)
{
{
Expand Down
40 changes: 40 additions & 0 deletions include/graphics/LVGL/LVGLConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "graphics/LVGL/LVGLDriver.h"
#include "graphics/LVGL/LVGL_ST7789_Driver.h"
#include "graphics/driver/DisplayDriverConfig.h"
#include "strings.h"
#include "util/ILog.h"

class DisplayDeviceDriver;

/**
* @brief Runtime configuration class for lvgl driver
*
*/
class LVGLConfig
{
public:
uint16_t screenWidth = 0;
uint16_t screenHeight = 0;

LVGLConfig(void);
LVGLConfig(const DisplayDriverConfig &cfg);
void init(void);
lv_display_t *create(uint32_t hor_res, uint32_t ver_res);
void touchpad_read(lv_indev_t *indev_driver, lv_indev_data_t *data);

bool hasButton(void);
bool hasTouch(void);
bool light(void);

uint8_t getBrightness(void);
void setBrightness(uint8_t setBrightness);

~LVGLConfig();

protected:
private:
const DisplayDriverConfig *config;
DisplayDeviceDriver *lvglDeviceDriver;
};
130 changes: 130 additions & 0 deletions include/graphics/LVGL/LVGLDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#pragma once

#ifdef LVGL_DRIVER
#include "drivers/display/lcd/lv_lcd_generic_mipi.h"
#include "graphics/driver/DisplayDriverConfig.h"
#include "graphics/driver/TFTDriver.h"
#include "input/InputDriver.h"
#include "util/ILog.h"

/**
* Base class for all specific LVGL drivers classes
*/
template <class LVGL> class LVGLDriver : public TFTDriver<LVGL>
{
public:
const uint32_t defaultScreenTimeout = 60 * 1000;
const uint32_t defaultScreenLockTimeout = 5 * 1000;
const uint32_t defaultBrightness = 153;

LVGLDriver(uint16_t width, uint16_t height);
LVGLDriver(const DisplayDriverConfig &cfg);
void init(DeviceGUI *gui) override;
bool hasTouch(void) override;
bool hasButton(void) override { return lvgldriver->hasButton(); }
bool hasLight(void) override { return lvgldriver->light(); }
bool isPowersaving(void) override { return powerSaving; }
void task_handler(void) override;

uint8_t getBrightness(void) override { return lvgldriver->getBrightness(); }
void setBrightness(uint8_t brightness) override {} // TODO

uint16_t getScreenTimeout() override { return screenTimeout / 1000; }
void setScreenTimeout(uint16_t timeout) override { screenTimeout = timeout * 1000; };

~LVGLDriver() { delete lvgldriver; }

protected:
void init_lvgl(void);
static void touchpad_read(lv_indev_t *indev_driver, lv_indev_data_t *data)
{
return lvgldriver->touchpad_read(indev_driver, data);
}

uint32_t screenTimeout;
uint32_t lastBrightness;
bool powerSaving;

private:
static LVGL *lvgldriver;
lv_display_t *display;
size_t bufsize;
std::pair<lv_color_t *, lv_color_t *> drawBuffer = {nullptr, nullptr};
};

template <class LVGL> LVGL *LVGLDriver<LVGL>::lvgldriver = nullptr;

template <class LVGL>
LVGLDriver<LVGL>::LVGLDriver(uint16_t width, uint16_t height)
: TFTDriver<LVGL>(lvgldriver ? lvgldriver : new LVGL, width, height), screenTimeout(defaultScreenTimeout),
lastBrightness(defaultBrightness), powerSaving(false), display(nullptr), bufsize(0)
{
lvgldriver = this->tft;
}

template <class LVGL>
LVGLDriver<LVGL>::LVGLDriver(const DisplayDriverConfig &cfg)
: TFTDriver<LVGL>(lvgldriver ? lvgldriver : new LVGL(cfg), cfg.width(), cfg.height()), screenTimeout(defaultScreenTimeout),
lastBrightness(defaultBrightness), powerSaving(false), display(nullptr), bufsize(0)
{
lvgldriver = this->tft;
}

template <class LVGL> void LVGLDriver<LVGL>::init(DeviceGUI *gui)
{
ILOG_DEBUG("LVGLDriver<LVGL>::init...");
init_lvgl();
TFTDriver<LVGL>::init(gui);

// LVGL: setup display device driver
ILOG_DEBUG("LVGL display driver create...");
display = lvgldriver->create(DisplayDriver::screenWidth, DisplayDriver::screenHeight);

std::pair<lv_color_t *, lv_color_t *> draw_buffers = {nullptr, nullptr};
const auto buffer_size =
DisplayDriver::screenWidth * DisplayDriver::screenHeight * lv_color_format_get_size(lv_display_get_color_format(display));

ILOG_INFO("allocating %d bytes for LVGL draw buffers", buffer_size);
// ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), ESP_DMA_MALLOC_FLAG_PSRAM, draw_buffers.first,
// nullptr)); ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), ESP_DMA_MALLOC_FLAG_PSRAM,
// draw_buffers.second, nullptr));

draw_buffers.first = (lv_color_t *)lv_malloc(buffer_size);
if (draw_buffers.first == nullptr) {
LV_LOG_ERROR("display draw buffer malloc failed");
return;
}

draw_buffers.second = (lv_color_t *)lv_malloc(buffer_size);
if (draw_buffers.second == nullptr) {
LV_LOG_ERROR("display buffer malloc failed");
lv_free(draw_buffers.first);
return;
}
lv_display_set_buffers(display, draw_buffers.first, draw_buffers.second, buffer_size, LV_DISPLAY_RENDER_MODE_PARTIAL);

if (hasTouch()) {
lv_indev_t *indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, touchpad_read);
lv_indev_set_display(indev, this->display);
}
}

template <class LGFX> void LVGLDriver<LGFX>::init_lvgl(void)
{
lvgldriver->init();
lvgldriver->setBrightness(defaultBrightness);
// lvgldriver->fillScreen(LGFX::color565(0x3D, 0xDA, 0x83));
}

template <class LGFX> bool LVGLDriver<LGFX>::hasTouch(void)
{
return lvgldriver->hasTouch();
}

template <class LGFX> void LVGLDriver<LGFX>::task_handler(void)
{
DisplayDriver::task_handler();
}
#endif
25 changes: 25 additions & 0 deletions include/graphics/LVGL/LVGL_ST7789_Driver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#ifdef LVGL_DRIVER

#include "drivers/display/st7789/lv_st7789.h"
#include "graphics/driver/DisplayDeviceDriver.h"
#include "graphics/driver/DisplayDriverConfig.h"

class LVGL_ST7789_Driver : public DisplayDeviceDriver
{
public:
LVGL_ST7789_Driver(uint16_t width, uint16_t height);
void init(int16_t spiBus, int16_t sclk, int16_t mosi, int16_t miso, int16_t dc, int16_t rst, int16_t cs);
lv_display_t *create(uint32_t hor_res, uint32_t ver_res);

protected:
private:
LVGL_ST7789_Driver(const LVGL_ST7789_Driver &) = delete;
LVGL_ST7789_Driver &operator=(const LVGL_ST7789_Driver &) = delete;

static void lcd_send_cmd_cb(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size);
static void lcd_send_color_cb(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size);
};

#endif
35 changes: 35 additions & 0 deletions include/graphics/LVGL/LVGL_T_DECK.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#ifdef LVGL_DRIVER

#include "graphics/LVGL/LVGLDriver.h"
#include "lvgl.h"
#include "stdint.h"

class LVGL_ST7789_Driver;

class LVGL_TDECK //: public LVGLDriver<LVGL_TDECK>
{
public:
static constexpr uint16_t screenWidth = 320;
static constexpr uint16_t screenHeight = 240;

LVGL_TDECK(void);
LVGL_TDECK(const DisplayDriverConfig &cfg);

void init(void);
bool hasButton(void) { return true; }
bool hasTouch(void) { return true; }
bool light(void) { return true; }
uint8_t getBrightness(void) { return 128; }
void setBrightness(uint8_t setBrightness) {}

lv_display_t *create(uint32_t hor_res, uint32_t ver_res);
void touchpad_read(lv_indev_t *indev_driver, lv_indev_data_t *data);

protected:
private:
LVGL_ST7789_Driver *driver;
};

#endif
31 changes: 31 additions & 0 deletions include/graphics/driver/DisplayDeviceDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "stdint.h"

/**
* Base class for all implemented display device drivers
*/
class DisplayDeviceDriver
{
public:
DisplayDeviceDriver(uint16_t width, uint16_t height) : screenWidth(width), screenHeight(height){};

virtual void init(void) {}
virtual lv_display_t *create(uint32_t hor_res, uint32_t ver_res) = 0;

virtual uint8_t getBrightness(void) const { return 128; }
virtual void setBrightness(uint8_t brightness) {}

virtual uint16_t getScreenTimeout() const { return 0; }
virtual void setScreenTimeout(uint16_t timeout) {}

virtual ~DisplayDeviceDriver() = default;

protected:
const uint16_t screenWidth;
const uint16_t screenHeight;

private:
DisplayDeviceDriver(const DisplayDeviceDriver &) = delete;
DisplayDeviceDriver &operator=(const DisplayDeviceDriver &) = delete;
};
5 changes: 5 additions & 0 deletions include/graphics/driver/DisplayDriverConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ class DisplayDriver;
class DisplayDriverConfig
{
public:
enum struct driver_t { LGFX, LVGL, ADAFRUIT, OTHER };

enum struct device_t {
NONE,
CUSTOM_TFT,
CUSTOM_OLED,
CUSTOM_EINK,
X11,
SDL2,
THMI,
TDECK,
INDICATOR,
Expand All @@ -37,6 +40,7 @@ class DisplayDriverConfig

struct panel_config_t {
char *type = nullptr;
driver_t driver = driver_t::LGFX;
uint16_t panel_width = 0;
uint16_t panel_height = 0;
bool rotation = false;
Expand Down Expand Up @@ -163,6 +167,7 @@ class DisplayDriverConfig
private:
friend class DisplayDriverFactory;
friend class LGFXConfig;
friend class LVGLConfig;

enum device_t _device;
panel_config_t _panel;
Expand Down
23 changes: 23 additions & 0 deletions include/graphics/driver/EINKDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "graphics/driver/DisplayDriver.h"

template <class EINK> class EINKDriver : public DisplayDriver
{
public:
EINKDriver(EINK *eink, uint16_t width, uint16_t height);
void init(DeviceGUI *gui) override;

protected:
EINK *einkDriver;
};

template <class EINK>
EINKDriver<EINK>::EINKDriver(EINK *eink, uint16_t width, uint16_t height) : DisplayDriver(width, height), einkDriver(eink)
{
}

template <class EINK> void EINKDriver<EINK>::init(DeviceGUI *gui)
{
DisplayDriver::init(gui);
}
4 changes: 4 additions & 0 deletions include/graphics/driver/TFTDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

#include "graphics/driver/DisplayDriver.h"

#ifdef ARCH_PORTDUINO
#include "Common.h" // millis()
#endif

template <class TFT> class TFTDriver : public DisplayDriver
{
public:
Expand Down
Loading