diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..58e1857 --- /dev/null +++ b/.clang-format @@ -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 diff --git a/boards/esp32-s3-lcd-43/DisplayDriverGFX.cpp b/boards/esp32-s3-lcd-43/DisplayDriverGFX.cpp index a186ab7..d94f30b 100644 --- a/boards/esp32-s3-lcd-43/DisplayDriverGFX.cpp +++ b/boards/esp32-s3-lcd-43/DisplayDriverGFX.cpp @@ -1,256 +1,244 @@ -#include "DisplayDriverGFX.h" +#include "LovyanPins.h" #include "board_config.h" +#include #include + +// 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 #include +#include +#include "LovyanPins.h" +#include "board_config.h" +#include "DisplayDriverGFX.h" -#ifndef BLACK -#define BLACK 0x0000 -#endif -#ifndef WHITE -#define WHITE 0xFFFF -#endif -#ifndef RED -#define RED 0xF800 -#endif +// ── Globals ── +static LGFX* _gfx = nullptr; +static ESP_IOExpander* _expander = nullptr; -// CH422G logical pin numbers -#define EXIO_TP_RST IO_EXPANDER_PIN_NUM_1 -#define EXIO_LCD_BL IO_EXPANDER_PIN_NUM_2 -#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 +// ── Forward declarations ── +static void initExpander(); +static void initDisplay(); -static ESP_IOExpander* expander = nullptr; +// ── Dimensions ── +static constexpr int DISP_W = 800; +static constexpr int DISP_H = 480; -// ── IO Expander ── - -void DisplayDriverGFX::expanderInit() { - Serial.println("[IO] IO expander init..."); - expander = new ESP_IOExpander_CH422G( - I2C_MASTER_NUM, +// ── Expander initialization ── +static void initExpander() { + Serial.println("IO expander init..."); + + // Initialize I2C for expander + 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(); - expander->multiPinMode( - EXIO_TP_RST | EXIO_LCD_BL | EXIO_LCD_RST | EXIO_SD_CS | EXIO_USB_SEL, - OUTPUT - ); - // Deassert resets, backlight OFF for now - expander->multiDigitalWrite( - EXIO_TP_RST | EXIO_LCD_RST | EXIO_SD_CS, - 0xFF - ); - expander->digitalWrite(EXIO_LCD_BL, LOW); - Serial.println("[IO] CH422G initialized"); + _expander->init(); + _expander->begin(); + + // Set all pins to output + _expander->multiPinMode(TP_RST | LCD_BL | LCD_RST | SD_CS | USB_SEL, OUTPUT); + + // Reset sequence + _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 ── +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) { - if (expander) { - expander->digitalWrite(EXIO_LCD_BL, on ? HIGH : LOW); - Serial.printf("[GFX] Backlight %s\n", on ? "ON" : "OFF"); + if (_expander) { + _expander->digitalWrite(LCD_BL, on ? HIGH : LOW); } } -// ── Touch ── - -void DisplayDriverGFX::touchInit() { - Wire.begin(I2C_MASTER_SDA, I2C_MASTER_SCL); - 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); - } +int DisplayDriverGFX::width() { + return DISP_W; } +int DisplayDriverGFX::height() { + return DISP_H; +} + +// ── Touch handling ── + TouchEvent DisplayDriverGFX::readTouch() { - TouchEvent ev = { false, 0, 0 }; - Wire.beginTransmission(GT911_ADDR); - if (Wire.endTransmission() != 0) return ev; - - // Read touch status register (0x814E) - 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(); - uint8_t touches = status & 0x0F; - - if ((status & 0x80) && touches > 0 && touches <= 5) { - // Read first touch point (0x8150) - Wire.beginTransmission(GT911_ADDR); - Wire.write(0x81); - 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; + TouchEvent evt; + + if (!_gfx) return evt; + + int32_t x, y; + if (_gfx->getTouch(&x, &y)) { + evt.pressed = true; + evt.x = static_cast(x); + evt.y = static_cast(y); + + // Track press start + if (!_lastTouch.pressed) { + _pressStartMs = millis(); + _isHolding = false; } } - - // Clear status - Wire.beginTransmission(GT911_ADDR); - Wire.write(0x81); - Wire.write(0x4E); - Wire.write(0x00); - Wire.endTransmission(); - - return ev; + + _lastTouch = evt; + return evt; } int DisplayDriverGFX::dashboardTouch(int x, int y) { - // Unified 2x2 grid - int col = (x * 2) / DISPLAY_WIDTH; // 0 or 1 - int row = (y * 2) / DISPLAY_HEIGHT; // 0 or 1 - return row * 2 + col; // 0, 1, 2, or 3 + // Dashboard tiles: 2 rows × 4 columns + constexpr int cols = 4; + constexpr int rows = 2; + 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) { - TouchEvent ev = readTouch(); + HoldState state; - if (ev.pressed) { - if (!_lastTouched) { - _holdStart = millis(); - _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}; + if (!_lastTouch.pressed) { + _isHolding = false; + return state; } -} -void DisplayDriverGFX::updateHint() { - // placeholder for idle hint animation -} - -// ── Display ── - -void DisplayDriverGFX::begin() { - // 1. Touch (I2C on GPIO 8/9) - touchInit(); - 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; + + unsigned long elapsed = millis() - _pressStartMs; + + if (!_isHolding) { + // Start tracking hold + _isHolding = true; } - - Serial.printf("[GFX] Display OK: %dx%d\n", DISPLAY_WIDTH, DISPLAY_HEIGHT); - Serial.printf("[MEM] Free heap: %d | Free PSRAM: %d\n", - ESP.getFreeHeap(), ESP.getFreePsram()); - - // 4. Clear and backlight on - _gfx->fillScreen(BLACK); - setBacklight(true); - drawBoot(); + + state.active = true; + state.progress = static_cast(elapsed) / static_cast(holdMs); + + if (state.progress >= 1.0f) { + state.progress = 1.0f; + state.completed = true; + } + + return state; } -int DisplayDriverGFX::width() { return _gfx ? _gfx->width() : DISPLAY_WIDTH; } -int DisplayDriverGFX::height() { return _gfx ? _gfx->height() : DISPLAY_HEIGHT; } - -// ── Render (state machine driven) ── +// ── Rendering ── void DisplayDriverGFX::render(const ScreenState& state) { if (!_gfx) return; - switch (state.screen) { - case ScreenID::BOOT: drawBoot(); break; - case ScreenID::DASHBOARD: drawDashboard(state); break; - case ScreenID::ALERT: drawAlert(state); break; - case ScreenID::OFF: drawOff(); break; - default: drawBoot(); break; + + // Clear with background color + _gfx->fillScreen(0x001030); // Dark blue + + if (!state.showDashboard) { + // Show alert/message screen + renderAlert(state); + return; } + + // Draw dashboard tiles + constexpr int cols = 4; + constexpr int rows = 2; + constexpr int tileW = DISP_W / cols; + constexpr int tileH = DISP_H / rows; + constexpr int margin = 8; + + 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->setCursor(x + 10, y + 10); + _gfx->print(state.dashTiles[i].label); + } + + // Draw WiFi status + _gfx->setTextSize(1); + _gfx->setCursor(DISP_W - 100, 10); + _gfx->printf("WiFi: %s", state.wifiConnected ? "ON" : "OFF"); } -void DisplayDriverGFX::drawBoot() { +void DisplayDriverGFX::updateHint() { if (!_gfx) return; - _gfx->fillScreen(BLACK); - _gfx->setTextColor(WHITE); - _gfx->setTextSize(4); - _gfx->setCursor(250, 200); - _gfx->println("Klubhaus Alert"); - _gfx->setTextSize(2); - _gfx->setCursor(300, 260); - _gfx->println("Booting..."); + + 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(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); } -void DisplayDriverGFX::drawDashboard(const ScreenState& state) { - if (!_gfx) return; - _gfx->fillScreen(BLACK); - _gfx->setTextColor(WHITE); +// 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->setCursor(20, 20); - _gfx->println("KLUBHAUS DASHBOARD"); - _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); + _gfx->setCursor(200, 200); + _gfx->print("Alert Mode"); } - -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); -} - diff --git a/boards/esp32-s3-lcd-43/DisplayDriverGFX.h b/boards/esp32-s3-lcd-43/DisplayDriverGFX.h index a4a3614..5746fb3 100644 --- a/boards/esp32-s3-lcd-43/DisplayDriverGFX.h +++ b/boards/esp32-s3-lcd-43/DisplayDriverGFX.h @@ -1,29 +1,42 @@ #pragma once -#include -#include +#include +#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 { public: + // ── IDisplayDriver ── void begin() override; void setBacklight(bool on) override; void render(const ScreenState& state) override; + TouchEvent readTouch() override; - int dashboardTouch(int x, int y) override; + int dashboardTouch(int x, int y) override; HoldState updateHold(unsigned long holdMs) override; void updateHint() override; - int width() override; - int height() override; + + int width() override; + int height() override; + + // ── Internal ── + static DisplayDriverGFX& instance(); private: - void expanderInit(); - 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; + // Touch handling + TouchEvent _lastTouch = {false, 0, 0}; + unsigned long _pressStartMs = 0; + bool _isHolding = false; }; - diff --git a/boards/esp32-s3-lcd-43/LovyanPins.h b/boards/esp32-s3-lcd-43/LovyanPins.h new file mode 100644 index 0000000..1c7c3e3 --- /dev/null +++ b/boards/esp32-s3-lcd-43/LovyanPins.h @@ -0,0 +1,118 @@ +#pragma once + +#define LGFX_USE_V1 +#include +#include +#include + +// ── 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); + } +}; diff --git a/boards/esp32-s3-lcd-43/board_config.h b/boards/esp32-s3-lcd-43/board_config.h index a712663..d79b261 100644 --- a/boards/esp32-s3-lcd-43/board_config.h +++ b/boards/esp32-s3-lcd-43/board_config.h @@ -1,41 +1,40 @@ #pragma once -#define BOARD_NAME "WS_S3_43" -#define DISPLAY_WIDTH 800 -#define DISPLAY_HEIGHT 480 +#define BOARD_NAME "WS_S3_43" +#define DISPLAY_WIDTH 800 +#define DISPLAY_HEIGHT 480 #define DISPLAY_ROTATION 0 // ── RGB parallel bus (from Westcott1 reference) ── -#define LCD_DE 5 -#define LCD_VSYNC 3 -#define LCD_HSYNC 46 -#define LCD_PCLK 7 +#define LCD_DE 5 +#define LCD_VSYNC 3 +#define LCD_HSYNC 46 +#define LCD_PCLK 7 -#define LCD_R0 1 -#define LCD_R1 2 -#define LCD_R2 42 -#define LCD_R3 41 -#define LCD_R4 40 +#define LCD_R0 1 +#define LCD_R1 2 +#define LCD_R2 42 +#define LCD_R3 41 +#define LCD_R4 40 -#define LCD_G0 39 -#define LCD_G1 0 -#define LCD_G2 45 -#define LCD_G3 48 -#define LCD_G4 47 -#define LCD_G5 21 +#define LCD_G0 39 +#define LCD_G1 0 +#define LCD_G2 45 +#define LCD_G3 48 +#define LCD_G4 47 +#define LCD_G5 21 -#define LCD_B0 14 -#define LCD_B1 38 -#define LCD_B2 18 -#define LCD_B3 17 -#define LCD_B4 10 +#define LCD_B0 14 +#define LCD_B1 38 +#define LCD_B2 18 +#define LCD_B3 17 +#define LCD_B4 10 // ── I2C bus (shared: CH422G + GT911) ── -#define I2C_MASTER_NUM ((i2c_port_t)0) -#define I2C_MASTER_SDA 8 -#define I2C_MASTER_SCL 9 +#define I2C_MASTER_NUM ((i2c_port_t)0) +#define I2C_MASTER_SDA 8 +#define I2C_MASTER_SCL 9 // ── GT911 Touch ── -#define GT911_ADDR 0x5D -#define TOUCH_INT -1 - +#define GT911_ADDR 0x5D +// #define TOUCH_INT -1 diff --git a/libraries/KlubhausCore/src/Config.h b/libraries/KlubhausCore/src/Config.h index acc636e..5e8ab29 100644 --- a/libraries/KlubhausCore/src/Config.h +++ b/libraries/KlubhausCore/src/Config.h @@ -3,21 +3,24 @@ #define FW_VERSION "5.1" // ── ntfy.sh ── -#define NTFY_SERVER "ntfy.sh" -#define ALERT_TOPIC "ALERT_klubhaus_topic" -#define SILENCE_TOPIC "SILENCE_klubhaus_topic" -#define ADMIN_TOPIC "ADMIN_klubhaus_topic" -#define STATUS_TOPIC "STATUS_klubhaus_topic" +#define NTFY_SERVER "ntfy.sh" +#define ALERT_TOPIC "ALERT_klubhaus_topic" +#define SILENCE_TOPIC "SILENCE_klubhaus_topic" +#define ADMIN_TOPIC "ADMIN_klubhaus_topic" +#define STATUS_TOPIC "STATUS_klubhaus_topic" // ── Timing ── -#define POLL_INTERVAL_MS 15000 -#define HEARTBEAT_INTERVAL_MS 300000 -#define BOOT_GRACE_MS 5000 -#define HOLD_TO_SILENCE_MS 3000 -#define ALERT_TIMEOUT_MS 120000 -#define SILENCE_DISPLAY_MS 10000 +#define POLL_INTERVAL_MS 15000 +#define HEARTBEAT_INTERVAL_MS 300000 +#define BOOT_GRACE_MS 5000 +#define HOLD_TO_SILENCE_MS 3000 +#define ALERT_TIMEOUT_MS 120000 +#define SILENCE_DISPLAY_MS 10000 #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) ── struct WiFiCred { diff --git a/mise.toml b/mise.toml index d3112d4..8276591 100644 --- a/mise.toml +++ b/mise.toml @@ -28,17 +28,21 @@ echo "[OK] TFT_eSPI 2.5.43 vendored + configured" """ [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 = """ #!/usr/bin/env bash set -euo pipefail -if [ ! -d "vendor/esp32-s3-lcd-43/GFX_Library_for_Arduino" ]; then - echo "Cloning Arduino_GFX..." - git clone --depth 1 --branch v1.6.5 \ - https://github.com/moononournation/Arduino_GFX.git \ - vendor/esp32-s3-lcd-43/GFX_Library_for_Arduino + +# Clone LovyanGFX (latest) +if [ ! -d "vendor/esp32-s3-lcd-43/LovyanGFX" ]; then + echo "Cloning LovyanGFX..." + git clone --depth 1 \ + https://github.com/lovyan03/LovyanGFX.git \ + vendor/esp32-s3-lcd-43/LovyanGFX +else + echo "LovyanGFX already exists, skipping" fi -echo "[OK] Arduino_GFX 1.6.5 vendored" +echo "[OK] LovyanGFX vendored" """ [tasks.install-libs] @@ -52,12 +56,13 @@ description = "Compile ESP32-32E sketch" depends = ["install-libs"] run = """ 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 ./vendor/esp32-32e \ - --build-property "compiler.cpp.extra_flags=-DDEBUG_MODE" \ + --libraries ./vendor/esp32-s3-lcd-43 \ + --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 \ - ./boards/esp32-32e + ./boards/esp32-s3-lcd-43 """ [tasks.upload-32e] @@ -84,7 +89,7 @@ run = """ arduino-cli compile \ --fqbn "esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" \ --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" \ --warnings default \ ./boards/esp32-s3-lcd-43 diff --git a/vendor/esp32-s3-lcd-43/LovyanGFX b/vendor/esp32-s3-lcd-43/LovyanGFX new file mode 160000 index 0000000..4299835 --- /dev/null +++ b/vendor/esp32-s3-lcd-43/LovyanGFX @@ -0,0 +1 @@ +Subproject commit 42998359d8a2eaf188643da7813122c6c3efd2fd