refactor(esp32-s3-lcd-43): remove IO expander and use LovyanGFX backlight
This commit is contained in:
@@ -1,60 +1,28 @@
|
|||||||
|
// boards/esp32-s3-lcd-43/DisplayDriverGFX.cpp
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Wire.h>
|
|
||||||
#include <ESP_IOExpander_Library.h>
|
|
||||||
#include "LovyanPins.h"
|
#include "LovyanPins.h"
|
||||||
#include "board_config.h"
|
#include "board_config.h"
|
||||||
#include "DisplayDriverGFX.h"
|
#include "DisplayDriverGFX.h"
|
||||||
|
|
||||||
// ── Globals ──
|
// ── Globals ──
|
||||||
static LGFX* _gfx = nullptr;
|
static LGFX* _gfx = nullptr;
|
||||||
static ESP_IOExpander* _expander = nullptr;
|
|
||||||
|
|
||||||
// ── Forward declarations ──
|
// ── Forward declarations ──
|
||||||
static void initExpander();
|
|
||||||
static void initDisplay();
|
static void initDisplay();
|
||||||
|
|
||||||
// ── Dimensions ──
|
// ── Dimensions ──
|
||||||
static constexpr int DISP_W = 800;
|
static constexpr int DISP_W = 800;
|
||||||
static constexpr int DISP_H = 480;
|
static constexpr int DISP_H = 480;
|
||||||
|
|
||||||
// ── Expander initialization (from Westcott) ──
|
|
||||||
static void initExpander() {
|
|
||||||
Serial.println("IO expander init...");
|
|
||||||
|
|
||||||
// Initialize I2C for expander (port 0)
|
|
||||||
Wire.begin(TOUCH_SDA, TOUCH_SCL);
|
|
||||||
|
|
||||||
_expander = new ESP_IOExpander_CH422G(
|
|
||||||
(i2c_port_t)I2C_NUM_0,
|
|
||||||
ESP_IO_EXPANDER_I2C_CH422G_ADDRESS
|
|
||||||
);
|
|
||||||
_expander->init();
|
|
||||||
_expander->begin();
|
|
||||||
|
|
||||||
// Set all pins to output
|
|
||||||
_expander->multiPinMode(TP_RST | LCD_BL | LCD_RST | SD_CS | USB_SEL, OUTPUT);
|
|
||||||
|
|
||||||
// Reset sequence for LCD
|
|
||||||
_expander->digitalWrite(LCD_RST, LOW);
|
|
||||||
delay(50);
|
|
||||||
_expander->digitalWrite(LCD_RST, HIGH);
|
|
||||||
delay(150);
|
|
||||||
|
|
||||||
// Turn on backlight
|
|
||||||
_expander->digitalWrite(LCD_BL, HIGH);
|
|
||||||
|
|
||||||
Serial.println("IO expander ready");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Display initialization ──
|
// ── Display initialization ──
|
||||||
static void initDisplay() {
|
static void initDisplay() {
|
||||||
Serial.println("LovyanGFX init...");
|
Serial.println("LovyanGFX init...");
|
||||||
|
|
||||||
_gfx = new LGFX();
|
_gfx = new LGFX();
|
||||||
_gfx->init();
|
_gfx->init();
|
||||||
_gfx->setRotation(1); // Landscape
|
_gfx->setRotation(1); // Landscape
|
||||||
_gfx->fillScreen(0x000000);
|
_gfx->fillScreen(0x000000);
|
||||||
|
|
||||||
Serial.println("Display ready");
|
Serial.println("Display ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,13 +35,13 @@ DisplayDriverGFX& DisplayDriverGFX::instance() {
|
|||||||
// ── IDisplayDriver implementation ──
|
// ── IDisplayDriver implementation ──
|
||||||
|
|
||||||
void DisplayDriverGFX::begin() {
|
void DisplayDriverGFX::begin() {
|
||||||
initExpander();
|
|
||||||
initDisplay();
|
initDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayDriverGFX::setBacklight(bool on) {
|
void DisplayDriverGFX::setBacklight(bool on) {
|
||||||
if (_expander) {
|
if (_gfx) {
|
||||||
_expander->digitalWrite(LCD_BL, on ? HIGH : LOW);
|
// LovyanGFX handles backlight via setBrightness
|
||||||
|
_gfx->setBrightness(on ? 255 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,22 +57,22 @@ int DisplayDriverGFX::height() {
|
|||||||
|
|
||||||
TouchEvent DisplayDriverGFX::readTouch() {
|
TouchEvent DisplayDriverGFX::readTouch() {
|
||||||
TouchEvent evt;
|
TouchEvent evt;
|
||||||
|
|
||||||
if (!_gfx) return evt;
|
if (!_gfx) return evt;
|
||||||
|
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
if (_gfx->getTouch(&x, &y)) {
|
if (_gfx->getTouch(&x, &y)) {
|
||||||
evt.pressed = true;
|
evt.pressed = true;
|
||||||
evt.x = static_cast<int>(x);
|
evt.x = static_cast<int>(x);
|
||||||
evt.y = static_cast<int>(y);
|
evt.y = static_cast<int>(y);
|
||||||
|
|
||||||
// Track press start for hold detection
|
// Track press start for hold detection
|
||||||
if (!_lastTouch.pressed) {
|
if (!_lastTouch.pressed) {
|
||||||
_pressStartMs = millis();
|
_pressStartMs = millis();
|
||||||
_isHolding = false;
|
_isHolding = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastTouch = evt;
|
_lastTouch = evt;
|
||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
@@ -115,39 +83,39 @@ int DisplayDriverGFX::dashboardTouch(int x, int y) {
|
|||||||
constexpr int rows = 2;
|
constexpr int rows = 2;
|
||||||
constexpr int tileW = DISP_W / cols;
|
constexpr int tileW = DISP_W / cols;
|
||||||
constexpr int tileH = DISP_H / rows;
|
constexpr int tileH = DISP_H / rows;
|
||||||
|
|
||||||
if (x < 0 || x >= DISP_W || y < 0 || y >= DISP_H) {
|
if (x < 0 || x >= DISP_W || y < 0 || y >= DISP_H) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int col = x / tileW;
|
int col = x / tileW;
|
||||||
int row = y / tileH;
|
int row = y / tileH;
|
||||||
|
|
||||||
return row * cols + col;
|
return row * cols + col;
|
||||||
}
|
}
|
||||||
|
|
||||||
HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) {
|
HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) {
|
||||||
HoldState state;
|
HoldState state;
|
||||||
|
|
||||||
if (!_lastTouch.pressed) {
|
if (!_lastTouch.pressed) {
|
||||||
_isHolding = false;
|
_isHolding = false;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long elapsed = millis() - _pressStartMs;
|
unsigned long elapsed = millis() - _pressStartMs;
|
||||||
|
|
||||||
if (!_isHolding) {
|
if (!_isHolding) {
|
||||||
_isHolding = true;
|
_isHolding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.active = true;
|
state.active = true;
|
||||||
state.progress = static_cast<float>(elapsed) / static_cast<float>(holdMs);
|
state.progress = static_cast<float>(elapsed) / static_cast<float>(holdMs);
|
||||||
|
|
||||||
if (state.progress >= 1.0f) {
|
if (state.progress >= 1.0f) {
|
||||||
state.progress = 1.0f;
|
state.progress = 1.0f;
|
||||||
state.completed = true;
|
state.completed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,13 +123,13 @@ HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) {
|
|||||||
|
|
||||||
void DisplayDriverGFX::render(const ScreenState& state) {
|
void DisplayDriverGFX::render(const ScreenState& state) {
|
||||||
if (!_gfx) return;
|
if (!_gfx) return;
|
||||||
|
|
||||||
// Check if we need full redraw
|
// Check if we need full redraw
|
||||||
if (state.screen != _lastScreen) {
|
if (state.screen != _lastScreen) {
|
||||||
_needsRedraw = true;
|
_needsRedraw = true;
|
||||||
_lastScreen = state.screen;
|
_lastScreen = state.screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state.screen) {
|
switch (state.screen) {
|
||||||
case ScreenID::BOOT:
|
case ScreenID::BOOT:
|
||||||
if (_needsRedraw) {
|
if (_needsRedraw) {
|
||||||
@@ -173,18 +141,18 @@ void DisplayDriverGFX::render(const ScreenState& state) {
|
|||||||
_needsRedraw = false;
|
_needsRedraw = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ScreenID::OFF:
|
case ScreenID::OFF:
|
||||||
if (_needsRedraw) {
|
if (_needsRedraw) {
|
||||||
_gfx->fillScreen(0x000000);
|
_gfx->fillScreen(0x000000);
|
||||||
_needsRedraw = false;
|
_needsRedraw = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ScreenID::ALERT:
|
case ScreenID::ALERT:
|
||||||
drawAlert(state);
|
drawAlert(state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ScreenID::DASHBOARD:
|
case ScreenID::DASHBOARD:
|
||||||
if (_needsRedraw) {
|
if (_needsRedraw) {
|
||||||
drawDashboard(state);
|
drawDashboard(state);
|
||||||
@@ -198,18 +166,18 @@ void DisplayDriverGFX::drawAlert(const ScreenState& state) {
|
|||||||
uint32_t elapsed = millis() - state.alertStartMs;
|
uint32_t elapsed = millis() - state.alertStartMs;
|
||||||
uint8_t pulse = static_cast<uint8_t>(180.0f + 75.0f * sinf(elapsed / 300.0f));
|
uint8_t pulse = static_cast<uint8_t>(180.0f + 75.0f * sinf(elapsed / 300.0f));
|
||||||
uint16_t bg = _gfx->color565(pulse, 0, 0);
|
uint16_t bg = _gfx->color565(pulse, 0, 0);
|
||||||
|
|
||||||
_gfx->fillScreen(bg);
|
_gfx->fillScreen(bg);
|
||||||
_gfx->setTextColor(0xFFFF, bg);
|
_gfx->setTextColor(0xFFFF, bg);
|
||||||
|
|
||||||
_gfx->setTextSize(3);
|
_gfx->setTextSize(3);
|
||||||
_gfx->setCursor(10, 20);
|
_gfx->setCursor(10, 20);
|
||||||
_gfx->print(state.alertTitle.length() > 0 ? state.alertTitle.c_str() : "ALERT");
|
_gfx->print(state.alertTitle.length() > 0 ? state.alertTitle.c_str() : "ALERT");
|
||||||
|
|
||||||
_gfx->setTextSize(2);
|
_gfx->setTextSize(2);
|
||||||
_gfx->setCursor(10, 80);
|
_gfx->setCursor(10, 80);
|
||||||
_gfx->print(state.alertBody);
|
_gfx->print(state.alertBody);
|
||||||
|
|
||||||
_gfx->setTextSize(1);
|
_gfx->setTextSize(1);
|
||||||
_gfx->setCursor(10, DISP_H - 20);
|
_gfx->setCursor(10, DISP_H - 20);
|
||||||
_gfx->print("Hold to silence...");
|
_gfx->print("Hold to silence...");
|
||||||
@@ -217,44 +185,44 @@ void DisplayDriverGFX::drawAlert(const ScreenState& state) {
|
|||||||
|
|
||||||
void DisplayDriverGFX::drawDashboard(const ScreenState& state) {
|
void DisplayDriverGFX::drawDashboard(const ScreenState& state) {
|
||||||
_gfx->fillScreen(0x001030); // Dark blue
|
_gfx->fillScreen(0x001030); // Dark blue
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
_gfx->fillRect(0, 0, DISP_W, 30, 0x0220);
|
_gfx->fillRect(0, 0, DISP_W, 30, 0x0220);
|
||||||
_gfx->setTextColor(0xFFFF);
|
_gfx->setTextColor(0xFFFF);
|
||||||
_gfx->setTextSize(1);
|
_gfx->setTextSize(1);
|
||||||
_gfx->setCursor(5, 10);
|
_gfx->setCursor(5, 10);
|
||||||
_gfx->printf("KLUBHAUS");
|
_gfx->printf("KLUBHAUS");
|
||||||
|
|
||||||
// WiFi status
|
// WiFi status
|
||||||
_gfx->setCursor(DISP_W - 100, 10);
|
_gfx->setCursor(DISP_W - 100, 10);
|
||||||
_gfx->printf("WiFi:%s", state.wifiSsid.length() > 0 ? "ON" : "OFF");
|
_gfx->printf("WiFi:%s", state.wifiSsid.length() > 0 ? "ON" : "OFF");
|
||||||
|
|
||||||
|
|
||||||
// Tiles: 2 rows × 4 columns
|
// Tiles: 2 rows × 4 columns
|
||||||
constexpr int cols = 4;
|
constexpr int cols = 4;
|
||||||
constexpr int rows = 2;
|
constexpr int rows = 2;
|
||||||
constexpr int tileW = DISP_W / cols;
|
constexpr int tileW = DISP_W / cols;
|
||||||
constexpr int tileH = (DISP_H - 30) / rows;
|
constexpr int tileH = (DISP_H - 30) / rows;
|
||||||
constexpr int margin = 8;
|
constexpr int margin = 8;
|
||||||
|
|
||||||
// Draw placeholder tiles (8 total for 2x4 grid)
|
// Draw placeholder tiles (8 total for 2x4 grid)
|
||||||
const char* tileLabels[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
|
const char* tileLabels[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
int col = i % cols;
|
int col = i % cols;
|
||||||
int row = i / cols;
|
int row = i / cols;
|
||||||
|
|
||||||
int x = col * tileW + margin;
|
int x = col * tileW + margin;
|
||||||
int y = 30 + row * tileH + margin;
|
int y = 30 + row * tileH + margin;
|
||||||
int w = tileW - 2 * margin;
|
int w = tileW - 2 * margin;
|
||||||
int h = tileH - 2 * margin;
|
int h = tileH - 2 * margin;
|
||||||
|
|
||||||
// Tile background
|
// Tile background
|
||||||
_gfx->fillRoundRect(x, y, w, h, 8, 0x0220);
|
_gfx->fillRoundRect(x, y, w, h, 8, 0x0220);
|
||||||
|
|
||||||
// Tile border
|
// Tile border
|
||||||
_gfx->drawRoundRect(x, y, w, h, 8, 0xFFFF);
|
_gfx->drawRoundRect(x, y, w, h, 8, 0xFFFF);
|
||||||
|
|
||||||
// Tile number
|
// Tile number
|
||||||
_gfx->setTextColor(0xFFFF);
|
_gfx->setTextColor(0xFFFF);
|
||||||
_gfx->setTextSize(2);
|
_gfx->setTextSize(2);
|
||||||
@@ -265,15 +233,15 @@ void DisplayDriverGFX::drawDashboard(const ScreenState& state) {
|
|||||||
|
|
||||||
void DisplayDriverGFX::updateHint() {
|
void DisplayDriverGFX::updateHint() {
|
||||||
if (!_gfx) return;
|
if (!_gfx) return;
|
||||||
|
|
||||||
static uint32_t lastTime = 0;
|
static uint32_t lastTime = 0;
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (now - lastTime < 50) return;
|
if (now - lastTime < 50) return;
|
||||||
lastTime = now;
|
lastTime = now;
|
||||||
|
|
||||||
float t = (now % 2000) / 2000.0f;
|
float t = (now % 2000) / 2000.0f;
|
||||||
uint8_t v = static_cast<uint8_t>(30.0f + 30.0f * sinf(t * 2 * 3.14159f));
|
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);
|
uint16_t col = ((v >> 3) << 11) | ((v >> 2) << 5) | (v >> 3);
|
||||||
|
|
||||||
_gfx->drawCircle(DISP_W / 2, DISP_H / 2, 50, col);
|
_gfx->drawCircle(DISP_W / 2, DISP_H / 2, 50, col);
|
||||||
}
|
}
|
||||||
|
|||||||
10
mise.toml
10
mise.toml
@@ -7,7 +7,6 @@ description = "Install shared (platform-independent) libraries"
|
|||||||
run = """
|
run = """
|
||||||
arduino-cli lib install "ArduinoJson@7.4.1"
|
arduino-cli lib install "ArduinoJson@7.4.1"
|
||||||
arduino-cli lib install "NTPClient@3.2.1"
|
arduino-cli lib install "NTPClient@3.2.1"
|
||||||
arduino-cli lib install "ESP32_IO_Expander@0.0.4"
|
|
||||||
echo "[OK] Shared libraries installed"
|
echo "[OK] Shared libraries installed"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -78,13 +77,12 @@ description = "Compile ESP32-32E sketch"
|
|||||||
depends = ["install-libs"]
|
depends = ["install-libs"]
|
||||||
run = """
|
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@2.0.11:esp32:FlashSize=4M,PartitionScheme=default" \
|
||||||
--libraries ./libraries \
|
--libraries ./libraries \
|
||||||
--libraries ./vendor/esp32-s3-lcd-43 \
|
--libraries ./vendor/esp32-32e/TFT_eSPI \
|
||||||
--build-property "compiler.cpp.extra_flags=-DDEBUG_MODE -DBOARD_HAS_PSRAM" \
|
--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-s3-lcd-43
|
./boards/esp32-32e
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[tasks.upload-32e]
|
[tasks.upload-32e]
|
||||||
@@ -105,7 +103,7 @@ arduino-cli monitor --port "${PORT:-/dev/ttyUSB0}" --config baudrate=115200
|
|||||||
# ── ESP32-S3-LCD-4.3 ────────────────────────────────────
|
# ── ESP32-S3-LCD-4.3 ────────────────────────────────────
|
||||||
|
|
||||||
[tasks.compile-s3-43]
|
[tasks.compile-s3-43]
|
||||||
description = "Compile ESP32-S3-LCD-4.3 sketch"
|
description = "Compile ESP32-S3-LCD-4.3 sketch (Core 2.x)"
|
||||||
depends = ["install-libs"]
|
depends = ["install-libs"]
|
||||||
run = """
|
run = """
|
||||||
arduino-cli compile \
|
arduino-cli compile \
|
||||||
|
|||||||
Reference in New Issue
Block a user