Work in progress on native display driver and the ability to stop&restart lvgl driver

This commit is contained in:
Ken Van Hoeylandt 2025-08-14 22:12:40 +02:00
parent 166673596c
commit e63d9d9a56
11 changed files with 155 additions and 33 deletions

View File

@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd ST7789 GT911 PwmBacklight driver esp_adc
REQUIRES Tactility EspLcdNativeDisplay esp_lvgl_port esp_lcd ST7789 GT911 PwmBacklight driver esp_adc
)

View File

@ -0,0 +1,5 @@
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lcd
)

View File

@ -0,0 +1,3 @@
# EspLcdNativeDisplay
An implementation of `tt::hal::display::NativeDisplay` for display drivers that are built around the `esp_lcd` library.

View File

@ -0,0 +1,33 @@
#pragma once
#include <Tactility/hal/display/NativeDisplay.h>
#include <esp_lcd_panel_ops.h>
namespace tt::hal::display {
class EspLcdNativeDisplay final : public NativeDisplay {
esp_lcd_panel_handle_t panelHandle;
ColorFormat colorFormat;
uint16_t pixelWidth;
uint16_t pixelHeight;
public:
EspLcdNativeDisplay(
esp_lcd_panel_handle_t panelHandle,
ColorFormat colorFormat,
uint16_t pixelWidth,
uint16_t pixelHeight
) : panelHandle(panelHandle), colorFormat(colorFormat), pixelWidth(pixelWidth), pixelHeight(pixelHeight) {}
ColorFormat getColorFormat() const override { return colorFormat; }
bool drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) override {
return esp_lcd_panel_draw_bitmap(panelHandle, xStart, yStart, xEnd, yEnd, pixelData) == ESP_OK;
}
uint16_t getPixelWidth() const override { return pixelWidth; }
uint16_t getPixelHeight() const override { return pixelHeight; }
};
}

View File

@ -1,5 +1,5 @@
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd driver
REQUIRES Tactility esp_lvgl_port esp_lcd driver EspLcdNativeDisplay
)

View File

@ -7,7 +7,7 @@
#include <esp_lcd_panel_st7789.h>
#include <esp_lvgl_port.h>
#define TAG "st7789"
#define TAG "ST7789"
bool St7789Display::start() {
TT_LOG_I(TAG, "Starting");
@ -86,6 +86,29 @@ bool St7789Display::start() {
TT_LOG_E(TAG, "Failed to turn display on");
return false;
}
TT_LOG_I(TAG, "Finished");
return displayHandle != nullptr;
}
bool St7789Display::stop() {
if (getLvglDisplay() != nullptr) {
stopLvgl();
}
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
return false;
}
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
return false;
}
displayHandle = nullptr;
return true;
}
bool St7789Display::startLvgl() {
uint32_t buffer_size;
if (configuration->bufferSize == 0) {
buffer_size = configuration->horizontalResolution * configuration->verticalResolution / 10;
@ -120,26 +143,16 @@ bool St7789Display::start() {
};
displayHandle = lvgl_port_add_disp(&disp_cfg);
TT_LOG_I(TAG, "Finished");
return displayHandle != nullptr;
}
bool St7789Display::stop() {
assert(displayHandle != nullptr);
lvgl_port_remove_disp(displayHandle);
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
bool St7789Display::stopLvgl() {
if (displayHandle == nullptr) {
return false;
} else {
lvgl_port_remove_disp(displayHandle);
return true;
}
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
return false;
}
displayHandle = nullptr;
return true;
}
/**

View File

@ -1,6 +1,8 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include <Tactility/hal/display/DisplayDevice.h>
#include <EspLcdNativeDisplay.h>
#include <driver/spi_common.h>
#include <driver/gpio.h>
@ -72,27 +74,57 @@ public:
assert(configuration != nullptr);
}
std::string getName() const final { return "ST7789"; }
std::string getDescription() const final { return "ST7789 display"; }
std::string getName() const override { return "ST7789"; }
std::string getDescription() const override { return "ST7789 display"; }
bool start() final;
bool start() override;
bool stop() final;
bool stop() override;
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable createTouch() final { return configuration->touch; }
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable createTouch() override { return configuration->touch; }
void setBacklightDuty(uint8_t backlightDuty) final {
void setBacklightDuty(uint8_t backlightDuty) override {
if (configuration->backlightDutyFunction != nullptr) {
configuration->backlightDutyFunction(backlightDuty);
}
}
bool supportsBacklightDuty() const final { return configuration->backlightDutyFunction != nullptr; }
bool supportsBacklightDuty() const override { return configuration->backlightDutyFunction != nullptr; }
void setGammaCurve(uint8_t index) final;
uint8_t getGammaCurveCount() const final { return 4; };
void setGammaCurve(uint8_t index) override;
uint8_t getGammaCurveCount() const override { return 4; };
lv_display_t* _Nullable getLvglDisplay() const final { return displayHandle; }
// region LVGL
bool supportsLvgl() const override { return true; }
bool startLvgl() override;
bool stopLvgl() override;
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
// endregion
// region NativedDisplay
bool supportsNativeDisplay() const override { return true; }
std::shared_ptr<tt::hal::display::NativeDisplay> getNativeDisplay() override {
assert(displayHandle == nullptr); // Still attached to LVGL context. Call stopLvgl() first.
uint16_t width = configuration->swapXY ? configuration->verticalResolution : configuration->horizontalResolution;
uint16_t height = configuration->swapXY ? configuration->horizontalResolution : configuration->verticalResolution;
return std::make_shared<tt::hal::display::EspLcdNativeDisplay>(
panelHandle,
tt::hal::display::ColorFormat::RGB565,
width,
height
);
}
// endregion
};
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -36,7 +36,7 @@ public:
virtual ~Device() = default;
/** Unique identifier */
inline Id getId() const { return id; }
Id getId() const { return id; }
/** The type of device */
virtual Type getType() const = 0;

View File

@ -10,12 +10,15 @@ class TouchDevice;
namespace tt::hal::display {
class NativeDisplay;
class DisplayDevice : public Device {
public:
Type getType() const override { return Type::Display; }
/** Starts the driver */
virtual bool start() = 0;
virtual bool stop() = 0;
@ -35,6 +38,13 @@ public:
/** After start() returns true, this should return a valid pointer until stop() is called and returns true */
virtual lv_display_t* _Nullable getLvglDisplay() const = 0;
virtual bool supportsLvgl() const { return false; }
virtual bool startLvgl() { return false; }
virtual bool stopLvgl() { return false; }
virtual bool supportsNativeDisplay() const { return false; }
virtual std::shared_ptr<NativeDisplay> getNativeDisplay() { return nullptr; }
};
} // namespace tt::hal::display

View File

@ -0,0 +1,24 @@
#pragma once
namespace tt::hal::display {
enum class ColorFormat {
Monochrome, // 1 bpp
BGR565,
RGB565,
RGB888
};
class NativeDisplay {
public:
virtual ~NativeDisplay() = default;
virtual ColorFormat getColorFormat() const = 0;
virtual uint16_t getPixelWidth() const = 0;
virtual uint16_t getPixelHeight() const = 0;
virtual bool drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) = 0;
};
}

View File

@ -31,9 +31,11 @@ static std::shared_ptr<hal::display::DisplayDevice> initDisplay(const hal::Confi
display->setBacklightDuty(0);
}
lv_display_rotation_t rotation = app::display::getRotation();
if (rotation != lv_display_get_rotation(lv_display_get_default())) {
lv_display_set_rotation(lv_display_get_default(), rotation);
if (display->supportsLvgl() && display->startLvgl()) {
lv_display_rotation_t rotation = app::display::getRotation();
if (rotation != lv_display_get_rotation(lv_display_get_default())) {
lv_display_set_rotation(lv_display_get_default(), rotation);
}
}
return display;