chore(examples): add submodule and remove LVGL examples

This commit is contained in:
2026-02-16 23:09:37 -08:00
parent 257bc9aa82
commit 9f0e603215
8 changed files with 435 additions and 282 deletions

26
.clang-format Normal file
View File

@@ -0,0 +1,26 @@
# Arduino/C++ friendly format
BasedOnStyle: WebKit
# Indentation
IndentWidth: 4
TabWidth: 4
UseTab: Never
IndentCaseLabels: false
# Braces - keep opening brace on same line
BreakBeforeBraces: Attach
# Spacing (fixed)
SpaceBeforeParens: Never
SpaceAfterCStyleCast: false
PointerAlignment: Left
# Line length
ColumnLimit: 100
# Includes
SortIncludes: true
IncludeBlocks: Regroup
# Functions
KeepEmptyLinesAtTheStartOfBlocks: false

View File

@@ -1,256 +1,244 @@
#include "DisplayDriverGFX.h" #include "LovyanPins.h"
#include "board_config.h" #include "board_config.h"
#include <Arduino.h>
#include <ESP_IOExpander_Library.h> #include <ESP_IOExpander_Library.h>
// Global display instance
static LGFX* _gfx = nullptr;
static ESP_IOExpander* _expander = nullptr;
// Forward declarations
void initExpander();
void initDisplay();
// ── Expander initialization (from Westcott) ──
void initExpander()
{
Serial.println("IO expander init...");
#include <Arduino.h>
#include <Wire.h> #include <Wire.h>
#include <ESP_IOExpander_Library.h>
#include "LovyanPins.h"
#include "board_config.h"
#include "DisplayDriverGFX.h"
#ifndef BLACK // ── Globals ──
#define BLACK 0x0000 static LGFX* _gfx = nullptr;
#endif static ESP_IOExpander* _expander = nullptr;
#ifndef WHITE
#define WHITE 0xFFFF
#endif
#ifndef RED
#define RED 0xF800
#endif
// CH422G logical pin numbers // ── Forward declarations ──
#define EXIO_TP_RST IO_EXPANDER_PIN_NUM_1 static void initExpander();
#define EXIO_LCD_BL IO_EXPANDER_PIN_NUM_2 static void initDisplay();
#define EXIO_LCD_RST IO_EXPANDER_PIN_NUM_3
#define EXIO_SD_CS IO_EXPANDER_PIN_NUM_4
#define EXIO_USB_SEL IO_EXPANDER_PIN_NUM_5
static ESP_IOExpander* expander = nullptr; // ── Dimensions ──
static constexpr int DISP_W = 800;
static constexpr int DISP_H = 480;
// ── IO Expander ── // ── Expander initialization ──
static void initExpander() {
Serial.println("IO expander init...");
void DisplayDriverGFX::expanderInit() { // Initialize I2C for expander
Serial.println("[IO] IO expander init..."); Wire.begin(TOUCH_SDA, TOUCH_SCL);
expander = new ESP_IOExpander_CH422G(
I2C_MASTER_NUM, _expander = new ESP_IOExpander_CH422G(
(i2c_port_t)I2C_NUM_0,
ESP_IO_EXPANDER_I2C_CH422G_ADDRESS ESP_IO_EXPANDER_I2C_CH422G_ADDRESS
); );
expander->init(); _expander->init();
expander->begin(); _expander->begin();
expander->multiPinMode(
EXIO_TP_RST | EXIO_LCD_BL | EXIO_LCD_RST | EXIO_SD_CS | EXIO_USB_SEL, // Set all pins to output
OUTPUT _expander->multiPinMode(TP_RST | LCD_BL | LCD_RST | SD_CS | USB_SEL, OUTPUT);
);
// Deassert resets, backlight OFF for now // Reset sequence
expander->multiDigitalWrite( _expander->digitalWrite(LCD_RST, LOW);
EXIO_TP_RST | EXIO_LCD_RST | EXIO_SD_CS, delay(50);
0xFF _expander->digitalWrite(LCD_RST, HIGH);
); delay(150);
expander->digitalWrite(EXIO_LCD_BL, LOW);
Serial.println("[IO] CH422G initialized"); // Turn on backlight
_expander->digitalWrite(LCD_BL, HIGH);
Serial.println("IO expander ready");
}
// ── Display initialization ──
static void initDisplay() {
Serial.println("LovyanGFX init...");
_gfx = new LGFX();
_gfx->init();
_gfx->setRotation(1); // Landscape
_gfx->fillScreen(0x000000);
Serial.println("Display ready");
}
// ── Singleton ──
DisplayDriverGFX& DisplayDriverGFX::instance() {
static DisplayDriverGFX inst;
return inst;
}
// ── IDisplayDriver implementation ──
void DisplayDriverGFX::begin() {
initExpander();
initDisplay();
} }
void DisplayDriverGFX::setBacklight(bool on) { void DisplayDriverGFX::setBacklight(bool on) {
if (expander) { if (_expander) {
expander->digitalWrite(EXIO_LCD_BL, on ? HIGH : LOW); _expander->digitalWrite(LCD_BL, on ? HIGH : LOW);
Serial.printf("[GFX] Backlight %s\n", on ? "ON" : "OFF");
} }
} }
// ── Touch ── int DisplayDriverGFX::width() {
return DISP_W;
}
void DisplayDriverGFX::touchInit() { int DisplayDriverGFX::height() {
Wire.begin(I2C_MASTER_SDA, I2C_MASTER_SCL); return DISP_H;
Wire.beginTransmission(GT911_ADDR);
uint8_t err = Wire.endTransmission();
if (err == 0) {
Serial.println("[TOUCH] GT911 initialized");
} else {
Serial.printf("[TOUCH] GT911 not found (I2C err %d)\n", err);
}
} }
// ── Touch handling ──
TouchEvent DisplayDriverGFX::readTouch() { TouchEvent DisplayDriverGFX::readTouch() {
TouchEvent ev = { false, 0, 0 }; TouchEvent evt;
Wire.beginTransmission(GT911_ADDR);
if (Wire.endTransmission() != 0) return ev;
// Read touch status register (0x814E) if (!_gfx) return evt;
Wire.beginTransmission(GT911_ADDR);
Wire.write(0x81);
Wire.write(0x4E);
Wire.endTransmission(false);
Wire.requestFrom((uint8_t)GT911_ADDR, (uint8_t)1);
if (!Wire.available()) return ev;
uint8_t status = Wire.read(); int32_t x, y;
uint8_t touches = status & 0x0F; if (_gfx->getTouch(&x, &y)) {
evt.pressed = true;
evt.x = static_cast<int>(x);
evt.y = static_cast<int>(y);
if ((status & 0x80) && touches > 0 && touches <= 5) { // Track press start
// Read first touch point (0x8150) if (!_lastTouch.pressed) {
Wire.beginTransmission(GT911_ADDR); _pressStartMs = millis();
Wire.write(0x81); _isHolding = false;
Wire.write(0x50);
Wire.endTransmission(false);
Wire.requestFrom((uint8_t)GT911_ADDR, (uint8_t)4);
if (Wire.available() >= 4) {
uint8_t xl = Wire.read();
uint8_t xh = Wire.read();
uint8_t yl = Wire.read();
uint8_t yh = Wire.read();
ev.pressed = true;
ev.x = (xh << 8) | xl;
ev.y = (yh << 8) | yl;
} }
} }
// Clear status _lastTouch = evt;
Wire.beginTransmission(GT911_ADDR); return evt;
Wire.write(0x81);
Wire.write(0x4E);
Wire.write(0x00);
Wire.endTransmission();
return ev;
} }
int DisplayDriverGFX::dashboardTouch(int x, int y) { int DisplayDriverGFX::dashboardTouch(int x, int y) {
// Unified 2x2 grid // Dashboard tiles: 2 rows × 4 columns
int col = (x * 2) / DISPLAY_WIDTH; // 0 or 1 constexpr int cols = 4;
int row = (y * 2) / DISPLAY_HEIGHT; // 0 or 1 constexpr int rows = 2;
return row * 2 + col; // 0, 1, 2, or 3 constexpr int tileW = DISP_W / cols;
constexpr int tileH = DISP_H / rows;
if (x < 0 || x >= DISP_W || y < 0 || y >= DISP_H) {
return -1;
}
int col = x / tileW;
int row = y / tileH;
return row * cols + col;
} }
HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) { HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) {
TouchEvent ev = readTouch(); HoldState state;
if (ev.pressed) { if (!_lastTouch.pressed) {
if (!_lastTouched) { _isHolding = false;
_holdStart = millis(); return state;
_lastTouched = true;
}
unsigned long elapsed = millis() - _holdStart;
float progress = constrain((float)elapsed / holdMs, 0.0f, 1.0f);
if (elapsed >= holdMs) {
_lastTouched = false;
_holdStart = 0;
return {false, true, 1.0f};
}
return {true, false, progress};
} else {
_lastTouched = false;
_holdStart = 0;
return {false, false, 0.0f};
}
}
void DisplayDriverGFX::updateHint() {
// placeholder for idle hint animation
} }
// ── Display ── unsigned long elapsed = millis() - _pressStartMs;
void DisplayDriverGFX::begin() { if (!_isHolding) {
// 1. Touch (I2C on GPIO 8/9) // Start tracking hold
touchInit(); _isHolding = true;
delay(200);
// 2. IO expander
expanderInit();
// 3. RGB display
Serial.println("[GFX] GFX init...");
Arduino_ESP32RGBPanel* rgbPanel = new Arduino_ESP32RGBPanel(
LCD_DE, LCD_VSYNC, LCD_HSYNC, LCD_PCLK,
LCD_R0, LCD_R1, LCD_R2, LCD_R3, LCD_R4,
LCD_G0, LCD_G1, LCD_G2, LCD_G3, LCD_G4, LCD_G5,
LCD_B0, LCD_B1, LCD_B2, LCD_B3, LCD_B4,
0, // hsync_polarity
40, // hsync_front_porch
48, // hsync_pulse_width
88, // hsync_back_porch
0, // vsync_polarity
13, // vsync_front_porch
3, // vsync_pulse_width
32, // vsync_back_porch
1, // pclk_active_neg
16000000 // prefer_speed
);
_gfx = new Arduino_RGB_Display(
DISPLAY_WIDTH, DISPLAY_HEIGHT, rgbPanel,
DISPLAY_ROTATION, true
);
if (!_gfx->begin()) {
Serial.println("[GFX] *** Display init FAILED ***");
return;
} }
Serial.printf("[GFX] Display OK: %dx%d\n", DISPLAY_WIDTH, DISPLAY_HEIGHT); state.active = true;
Serial.printf("[MEM] Free heap: %d | Free PSRAM: %d\n", state.progress = static_cast<float>(elapsed) / static_cast<float>(holdMs);
ESP.getFreeHeap(), ESP.getFreePsram());
// 4. Clear and backlight on if (state.progress >= 1.0f) {
_gfx->fillScreen(BLACK); state.progress = 1.0f;
setBacklight(true); state.completed = true;
drawBoot();
} }
int DisplayDriverGFX::width() { return _gfx ? _gfx->width() : DISPLAY_WIDTH; } return state;
int DisplayDriverGFX::height() { return _gfx ? _gfx->height() : DISPLAY_HEIGHT; } }
// ── Render (state machine driven) ── // ── Rendering ──
void DisplayDriverGFX::render(const ScreenState& state) { void DisplayDriverGFX::render(const ScreenState& state) {
if (!_gfx) return; if (!_gfx) return;
switch (state.screen) {
case ScreenID::BOOT: drawBoot(); break; // Clear with background color
case ScreenID::DASHBOARD: drawDashboard(state); break; _gfx->fillScreen(0x001030); // Dark blue
case ScreenID::ALERT: drawAlert(state); break;
case ScreenID::OFF: drawOff(); break; if (!state.showDashboard) {
default: drawBoot(); break; // Show alert/message screen
} renderAlert(state);
return;
} }
void DisplayDriverGFX::drawBoot() { // Draw dashboard tiles
if (!_gfx) return; constexpr int cols = 4;
_gfx->fillScreen(BLACK); constexpr int rows = 2;
_gfx->setTextColor(WHITE); constexpr int tileW = DISP_W / cols;
_gfx->setTextSize(4); constexpr int tileH = DISP_H / rows;
_gfx->setCursor(250, 200); constexpr int margin = 8;
_gfx->println("Klubhaus Alert");
for (int i = 0; i < state.dashTiles.size(); i++) {
int col = i % cols;
int row = i / cols;
int x = col * tileW + margin;
int y = row * tileH + margin;
int w = tileW - 2 * margin;
int h = tileH - 2 * margin;
// Tile background
uint16_t tileColor = state.dashTiles[i].active ? 0x04A0 : 0x0220;
_gfx->fillRoundRect(x, y, w, h, 8, tileColor);
// Tile border
_gfx->drawRoundRect(x, y, w, h, 8, 0xFFFF);
// Tile label
_gfx->setTextColor(0xFFFF);
_gfx->setTextSize(2); _gfx->setTextSize(2);
_gfx->setCursor(300, 260); _gfx->setCursor(x + 10, y + 10);
_gfx->println("Booting..."); _gfx->print(state.dashTiles[i].label);
} }
void DisplayDriverGFX::drawDashboard(const ScreenState& state) { // Draw WiFi status
_gfx->setTextSize(1);
_gfx->setCursor(DISP_W - 100, 10);
_gfx->printf("WiFi: %s", state.wifiConnected ? "ON" : "OFF");
}
void DisplayDriverGFX::updateHint() {
if (!_gfx) return; if (!_gfx) return;
_gfx->fillScreen(BLACK);
_gfx->setTextColor(WHITE); static uint32_t lastTime = 0;
uint32_t now = millis();
if (now - lastTime < 50) return;
lastTime = now;
float t = (now % 2000) / 2000.0f;
uint8_t v = static_cast<uint8_t>(30.0f + 30.0f * sinf(t * 2 * 3.14159f));
uint16_t col = ((v >> 3) << 11) | ((v >> 2) << 5) | (v >> 3);
_gfx->drawCircle(DISP_W / 2, DISP_H / 2, 50, col);
}
// Helper for alert rendering (implement as needed)
void DisplayDriverGFX::renderAlert(const ScreenState& state) {
// Placeholder - implement based on your ScreenState fields
_gfx->setTextColor(0xFFFF);
_gfx->setTextSize(3); _gfx->setTextSize(3);
_gfx->setCursor(20, 20); _gfx->setCursor(200, 200);
_gfx->println("KLUBHAUS DASHBOARD"); _gfx->print("Alert Mode");
_gfx->setTextSize(2);
_gfx->setCursor(20, 80);
_gfx->printf("IP: %s", state.ipAddr.c_str());
_gfx->setCursor(20, 110);
_gfx->printf("RSSI: %d dBm", state.wifiRssi);
_gfx->setCursor(20, 140);
} }
void DisplayDriverGFX::drawAlert(const ScreenState& state) {
if (!_gfx) return;
_gfx->fillScreen(RED);
_gfx->setTextColor(WHITE);
_gfx->setTextSize(5);
_gfx->setCursor(200, 180);
_gfx->println("DOORBELL!");
_gfx->setTextSize(3);
_gfx->setCursor(100, 280);
const char* body = state.alertBody.c_str();
_gfx->println(state.alertBody.length() ? body : "Someone is at the door");
}
void DisplayDriverGFX::drawOff() {
if (!_gfx) return;
_gfx->fillScreen(BLACK);
setBacklight(false);
}

View File

@@ -1,29 +1,42 @@
#pragma once #pragma once
#include <IDisplayDriver.h> #include <Arduino.h>
#include <Arduino_GFX_Library.h> #include "ScreenState.h"
#include "IDisplayDriver.h"
struct TouchEvent {
bool pressed = false;
int x = 0;
int y = 0;
};
struct HoldState {
bool active = false;
bool completed = false;
float progress = 0.0f; // 0.0 1.0
};
class DisplayDriverGFX : public IDisplayDriver { class DisplayDriverGFX : public IDisplayDriver {
public: public:
// ── IDisplayDriver ──
void begin() override; void begin() override;
void setBacklight(bool on) override; void setBacklight(bool on) override;
void render(const ScreenState& state) override; void render(const ScreenState& state) override;
TouchEvent readTouch() override; TouchEvent readTouch() override;
int dashboardTouch(int x, int y) override; int dashboardTouch(int x, int y) override;
HoldState updateHold(unsigned long holdMs) override; HoldState updateHold(unsigned long holdMs) override;
void updateHint() override; void updateHint() override;
int width() override; int width() override;
int height() override; int height() override;
private: // ── Internal ──
void expanderInit(); static DisplayDriverGFX& instance();
void touchInit();
void drawBoot();
void drawDashboard(const ScreenState& state);
void drawAlert(const ScreenState& state);
void drawOff();
Arduino_RGB_Display* _gfx = nullptr;
bool _lastTouched = false;
unsigned long _holdStart = 0;
};
private:
// Touch handling
TouchEvent _lastTouch = {false, 0, 0};
unsigned long _pressStartMs = 0;
bool _isHolding = false;
};

View File

@@ -0,0 +1,118 @@
#pragma once
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
// ── Display dimensions ──
#define TFT_HOR_RES 800
#define TFT_VER_RES 480
// ── Touch I2C (from Westcott example) ──
#define TOUCH_SDA 8
#define TOUCH_SCL 9
#define TOUCH_INT 4
#define TOUCH_RST -1
// ── CH422G Expander pins ──
#define TP_RST 1
#define LCD_BL 2
#define LCD_RST 3
#define SD_CS 4
#define USB_SEL 5
class LGFX : public lgfx::LGFX_Device {
public:
lgfx::Bus_RGB _bus_instance;
lgfx::Panel_RGB _panel_instance;
lgfx::Touch_GT911 _touch_instance;
LGFX(void) {
// Panel config
{
auto cfg = _panel_instance.config();
cfg.memory_width = TFT_HOR_RES;
cfg.memory_height = TFT_VER_RES;
cfg.panel_width = TFT_HOR_RES;
cfg.panel_height = TFT_VER_RES;
cfg.offset_x = 0;
cfg.offset_y = 0;
_panel_instance.config(cfg);
}
// RGB parallel bus config (from Westcott)
{
auto cfg = _bus_instance.config();
cfg.panel = &_panel_instance;
// Blue channel
cfg.pin_d0 = 14;
cfg.pin_d1 = 38;
cfg.pin_d2 = 18;
cfg.pin_d3 = 17;
cfg.pin_d4 = 10;
// Green channel
cfg.pin_d5 = 39;
cfg.pin_d6 = 0;
cfg.pin_d7 = 45;
cfg.pin_d8 = 48;
cfg.pin_d9 = 47;
cfg.pin_d10 = 21;
// Red channel
cfg.pin_d11 = 1;
cfg.pin_d12 = 2;
cfg.pin_d13 = 42;
cfg.pin_d14 = 41;
cfg.pin_d15 = 40;
// Timing
cfg.pin_henable = 5;
cfg.pin_vsync = 3;
cfg.pin_hsync = 46;
cfg.pin_pclk = 7;
cfg.freq_write = 14000000;
cfg.hsync_polarity = 0;
cfg.hsync_front_porch = 20;
cfg.hsync_pulse_width = 10;
cfg.hsync_back_porch = 10;
cfg.vsync_polarity = 0;
cfg.vsync_front_porch = 10;
cfg.vsync_pulse_width = 10;
cfg.vsync_back_porch = 10;
cfg.pclk_active_neg = 0;
cfg.de_idle_high = 0;
cfg.pclk_idle_high = 0;
_bus_instance.config(cfg);
}
_panel_instance.setBus(&_bus_instance);
// Touch config (I2C port 1, address 0x14 - from Westcott!)
{
auto cfg = _touch_instance.config();
cfg.x_min = 0;
cfg.x_max = TFT_HOR_RES - 1;
cfg.y_min = 0;
cfg.y_max = TFT_VER_RES - 1;
cfg.pin_int = TOUCH_INT;
cfg.pin_rst = TOUCH_RST;
cfg.bus_shared = false;
cfg.offset_rotation = 0;
cfg.i2c_port = I2C_NUM_1; // IMPORTANT: Port 1, not 0!
cfg.pin_sda = TOUCH_SDA;
cfg.pin_scl = TOUCH_SCL;
cfg.freq = 400000;
cfg.i2c_addr = 0x14; // IMPORTANT: Address 0x14, not 0x5D!
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
setPanel(&_panel_instance);
}
};

View File

@@ -37,5 +37,4 @@
// ── GT911 Touch ── // ── GT911 Touch ──
#define GT911_ADDR 0x5D #define GT911_ADDR 0x5D
#define TOUCH_INT -1 // #define TOUCH_INT -1

View File

@@ -18,6 +18,9 @@
#define SILENCE_DISPLAY_MS 10000 #define SILENCE_DISPLAY_MS 10000
#define WIFI_CONNECT_TIMEOUT_MS 15000 #define WIFI_CONNECT_TIMEOUT_MS 15000
#define HTTP_TIMEOUT_MS 10000 #define HTTP_TIMEOUT_MS 10000
#define HINT_ANIMATION_MS 2000
#define HINT_MIN_BRIGHTNESS 30
#define HINT_MAX_BRIGHTNESS 60
// ── WiFi credential struct (populated in each board's secrets.h) ── // ── WiFi credential struct (populated in each board's secrets.h) ──
struct WiFiCred { struct WiFiCred {

View File

@@ -28,17 +28,21 @@ echo "[OK] TFT_eSPI 2.5.43 vendored + configured"
""" """
[tasks.install-libs-s3-43] [tasks.install-libs-s3-43]
description = "Vendor Arduino_GFX into vendor/esp32-s3-lcd-43" description = "Vendor LovyanGFX into vendor/esp32-s3-lcd-43"
run = """ run = """
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
if [ ! -d "vendor/esp32-s3-lcd-43/GFX_Library_for_Arduino" ]; then
echo "Cloning Arduino_GFX..." # Clone LovyanGFX (latest)
git clone --depth 1 --branch v1.6.5 \ if [ ! -d "vendor/esp32-s3-lcd-43/LovyanGFX" ]; then
https://github.com/moononournation/Arduino_GFX.git \ echo "Cloning LovyanGFX..."
vendor/esp32-s3-lcd-43/GFX_Library_for_Arduino git clone --depth 1 \
https://github.com/lovyan03/LovyanGFX.git \
vendor/esp32-s3-lcd-43/LovyanGFX
else
echo "LovyanGFX already exists, skipping"
fi fi
echo "[OK] Arduino_GFX 1.6.5 vendored" echo "[OK] LovyanGFX vendored"
""" """
[tasks.install-libs] [tasks.install-libs]
@@ -52,12 +56,13 @@ description = "Compile ESP32-32E sketch"
depends = ["install-libs"] depends = ["install-libs"]
run = """ run = """
arduino-cli compile \ arduino-cli compile \
--fqbn "esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default" \ --fqbn "esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" \
--libraries ./libraries \ --libraries ./libraries \
--libraries ./vendor/esp32-32e \ --libraries ./vendor/esp32-s3-lcd-43 \
--build-property "compiler.cpp.extra_flags=-DDEBUG_MODE" \ --build-property "compiler.cpp.extra_flags=-DDEBUG_MODE -DBOARD_HAS_PSRAM" \
--build-property "build.extra_flags=-DCONFIG_ESP32S3_OLD_I2C_LEGACY_DEVICE_COMPAT_MODE=1" \
--warnings default \ --warnings default \
./boards/esp32-32e ./boards/esp32-s3-lcd-43
""" """
[tasks.upload-32e] [tasks.upload-32e]
@@ -84,7 +89,7 @@ run = """
arduino-cli compile \ arduino-cli compile \
--fqbn "esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" \ --fqbn "esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" \
--libraries ./libraries \ --libraries ./libraries \
--libraries ./vendor/esp32-s3-lcd-43 \ --libraries ./vendor/esp32-s3-lcd-43/LovyanGFX \
--build-property "compiler.cpp.extra_flags=-DDEBUG_MODE -DBOARD_HAS_PSRAM" \ --build-property "compiler.cpp.extra_flags=-DDEBUG_MODE -DBOARD_HAS_PSRAM" \
--warnings default \ --warnings default \
./boards/esp32-s3-lcd-43 ./boards/esp32-s3-lcd-43

1
vendor/esp32-s3-lcd-43/LovyanGFX vendored Submodule

Submodule vendor/esp32-s3-lcd-43/LovyanGFX added at 42998359d8