refactor(Format code): Improve readability and structure
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "DisplayDriverTFT.h"
|
#include "DisplayDriverTFT.h"
|
||||||
|
|
||||||
#include <KlubhausCore.h>
|
#include <KlubhausCore.h>
|
||||||
|
|
||||||
extern DisplayManager display;
|
extern DisplayManager display;
|
||||||
@@ -35,7 +36,8 @@ void DisplayDriverTFT::setBacklight(bool on) { digitalWrite(PIN_LCD_BL, on ? HIG
|
|||||||
// ── Rendering ───────────────────────────────────────────────
|
// ── Rendering ───────────────────────────────────────────────
|
||||||
|
|
||||||
void DisplayDriverTFT::render(const ScreenState& st) {
|
void DisplayDriverTFT::render(const ScreenState& st) {
|
||||||
if(st.screen != _lastScreen || (st.screen == ScreenID::BOOT && st.bootStage != _lastBootStage)) {
|
if(st.screen != _lastScreen
|
||||||
|
|| (st.screen == ScreenID::BOOT && st.bootStage != _lastBootStage)) {
|
||||||
_needsRedraw = true;
|
_needsRedraw = true;
|
||||||
_lastScreen = st.screen;
|
_lastScreen = st.screen;
|
||||||
_lastBootStage = st.bootStage;
|
_lastBootStage = st.bootStage;
|
||||||
@@ -162,7 +164,7 @@ void DisplayDriverTFT::drawDashboard(const ScreenState& st) {
|
|||||||
_tft.setTextSize(2);
|
_tft.setTextSize(2);
|
||||||
int textLen = strlen(tileLabels[i]);
|
int textLen = strlen(tileLabels[i]);
|
||||||
int textW = textLen * 12;
|
int textW = textLen * 12;
|
||||||
_tft.setCursor(x + w/2 - textW/2, y + h/2 - 10);
|
_tft.setCursor(x + w / 2 - textW / 2, y + h / 2 - 10);
|
||||||
_tft.print(tileLabels[i]);
|
_tft.print(tileLabels[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +204,7 @@ TouchEvent DisplayDriverTFT::readTouch() {
|
|||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t DisplayDriverTFT::getRawTouchZ() {
|
uint16_t DisplayDriverTFT::getRawTouchZ() { return _tft.getTouchRawZ(); }
|
||||||
return _tft.getTouchRawZ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayDriverTFT::transformTouch(int* x, int* y) {
|
void DisplayDriverTFT::transformTouch(int* x, int* y) {
|
||||||
// Resistive touch panel is rotated 90° vs display - swap coordinates
|
// Resistive touch panel is rotated 90° vs display - swap coordinates
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ void DisplayDriverTFT::setBacklight(bool on) { digitalWrite(PIN_LCD_BL, on ? HIG
|
|||||||
// ── Rendering ───────────────────────────────────────────────
|
// ── Rendering ───────────────────────────────────────────────
|
||||||
|
|
||||||
void DisplayDriverTFT::render(const ScreenState& st) {
|
void DisplayDriverTFT::render(const ScreenState& st) {
|
||||||
if(st.screen != _lastScreen || (st.screen == ScreenID::BOOT && st.bootStage != _lastBootStage)) {
|
if(st.screen != _lastScreen
|
||||||
|
|| (st.screen == ScreenID::BOOT && st.bootStage != _lastBootStage)) {
|
||||||
_needsRedraw = true;
|
_needsRedraw = true;
|
||||||
_lastScreen = st.screen;
|
_lastScreen = st.screen;
|
||||||
_lastBootStage = st.bootStage;
|
_lastBootStage = st.bootStage;
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ void DisplayDriverGFX::render(const ScreenState& state) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Check if we need full redraw
|
// Check if we need full redraw
|
||||||
if(state.screen != _lastScreen || (state.screen == ScreenID::BOOT && state.bootStage != _lastBootStage)) {
|
if(state.screen != _lastScreen
|
||||||
|
|| (state.screen == ScreenID::BOOT && state.bootStage != _lastBootStage)) {
|
||||||
_needsRedraw = true;
|
_needsRedraw = true;
|
||||||
_lastScreen = state.screen;
|
_lastScreen = state.screen;
|
||||||
_lastBootStage = state.bootStage;
|
_lastBootStage = state.bootStage;
|
||||||
@@ -284,7 +285,7 @@ void DisplayDriverGFX::drawDashboard(const ScreenState& state) {
|
|||||||
// Tile label
|
// Tile label
|
||||||
_gfx->setTextColor(0xFFFF);
|
_gfx->setTextColor(0xFFFF);
|
||||||
_gfx->setTextSize(2);
|
_gfx->setTextSize(2);
|
||||||
_gfx->setCursor(x + w/2 - 10, y + h/2 - 10);
|
_gfx->setCursor(x + w / 2 - 10, y + h / 2 - 10);
|
||||||
_gfx->print(tileLabels[i]);
|
_gfx->print(tileLabels[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ public:
|
|||||||
int width() override;
|
int width() override;
|
||||||
int height() override;
|
int height() override;
|
||||||
|
|
||||||
|
// Dashboard tile mapping
|
||||||
|
int dashboardTouch(int x, int y);
|
||||||
|
|
||||||
// ── Internal ──
|
// ── Internal ──
|
||||||
static DisplayDriverGFX& instance();
|
static DisplayDriverGFX& instance();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
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"
|
||||||
PORT="/dev/ttyACM0"
|
PORT="/dev/ttyACM0"
|
||||||
LIBS="--libraries ./vendor/esp32-s3-lcd-43/LovyanGFX"
|
LIBS="--libraries ~/Arduino/libraries/LovyanGFX"
|
||||||
OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM -DLGFX_USE_V1"
|
OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM -DLGFX_USE_V1"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "IDisplayDriver.h"
|
#include "IDisplayDriver.h"
|
||||||
#include "ScreenState.h"
|
#include "ScreenState.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
/// Layout helper for dashboard tiles - computes positions based on constraints
|
/// Layout helper for dashboard tiles - computes positions based on constraints
|
||||||
@@ -10,50 +11,45 @@ public:
|
|||||||
/// Calculate tile layouts for the given display dimensions
|
/// Calculate tile layouts for the given display dimensions
|
||||||
/// Returns array of TileLayout (must have capacity for DASHBOARD_TILE_COUNT)
|
/// Returns array of TileLayout (must have capacity for DASHBOARD_TILE_COUNT)
|
||||||
/// Returns the number of columns and rows used
|
/// Returns the number of columns and rows used
|
||||||
static int calculateLayouts(
|
static int calculateLayouts(int displayW, int displayH, int headerH, int margin,
|
||||||
int displayW,
|
TileLayout* outLayouts, int* outCols, int* outRows) {
|
||||||
int displayH,
|
|
||||||
int headerH,
|
|
||||||
int margin,
|
|
||||||
TileLayout* outLayouts,
|
|
||||||
int* outCols,
|
|
||||||
int* outRows
|
|
||||||
) {
|
|
||||||
int contentH = displayH - headerH;
|
int contentH = displayH - headerH;
|
||||||
int tileCount = DASHBOARD_TILE_COUNT;
|
int tileCount = DASHBOARD_TILE_COUNT;
|
||||||
|
|
||||||
// Determine base grid based on display aspect ratio
|
// Determine base grid based on display aspect ratio
|
||||||
int cols, rows;
|
int cols, rows;
|
||||||
calculateGrid(tileCount, displayW, contentH, &cols, &rows);
|
calculateGrid(tileCount, displayW, contentH, &cols, &rows);
|
||||||
|
|
||||||
// Calculate base cell sizes
|
// Calculate base cell sizes
|
||||||
int cellW = displayW / cols;
|
int cellW = displayW / cols;
|
||||||
int cellH = contentH / rows;
|
int cellH = contentH / rows;
|
||||||
|
|
||||||
// Simple first-fit: place tiles in order, respecting min sizes
|
// Simple first-fit: place tiles in order, respecting min sizes
|
||||||
// For more complex layouts, tiles could specify preferred positions
|
// For more complex layouts, tiles could specify preferred positions
|
||||||
for(int i = 0; i < tileCount; i++) {
|
for(int i = 0; i < tileCount; i++) {
|
||||||
const DashboardTile& tile = DASHBOARD_TILES[i];
|
const DashboardTile& tile = DASHBOARD_TILES[i];
|
||||||
int tileCols = tile.constraint.minCols;
|
int tileCols = tile.constraint.minCols;
|
||||||
int tileRows = tile.constraint.minRows;
|
int tileRows = tile.constraint.minRows;
|
||||||
|
|
||||||
// Find next available position
|
// Find next available position
|
||||||
int col = 0, row = 0;
|
int col = 0, row = 0;
|
||||||
findNextPosition(outLayouts, i, cols, rows, &col, &row);
|
findNextPosition(outLayouts, i, cols, rows, &col, &row);
|
||||||
|
|
||||||
// Ensure tile fits within grid
|
// Ensure tile fits within grid
|
||||||
if(col + tileCols > cols) tileCols = cols - col;
|
if(col + tileCols > cols)
|
||||||
if(row + tileRows > rows) tileRows = rows - row;
|
tileCols = cols - col;
|
||||||
|
if(row + tileRows > rows)
|
||||||
|
tileRows = rows - row;
|
||||||
|
|
||||||
// Calculate pixel position
|
// Calculate pixel position
|
||||||
int x = col * cellW + margin;
|
int x = col * cellW + margin;
|
||||||
int y = headerH + row * cellH + margin;
|
int y = headerH + row * cellH + margin;
|
||||||
int w = tileCols * cellW - 2 * margin;
|
int w = tileCols * cellW - 2 * margin;
|
||||||
int h = tileRows * cellH - 2 * margin;
|
int h = tileRows * cellH - 2 * margin;
|
||||||
|
|
||||||
outLayouts[i] = {x, y, w, h, col, row, tileCols, tileRows};
|
outLayouts[i] = { x, y, w, h, col, row, tileCols, tileRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
*outCols = cols;
|
*outCols = cols;
|
||||||
*outRows = rows;
|
*outRows = rows;
|
||||||
return tileCount;
|
return tileCount;
|
||||||
@@ -61,17 +57,20 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// Calculate optimal grid dimensions based on display and tile constraints
|
/// Calculate optimal grid dimensions based on display and tile constraints
|
||||||
static void calculateGrid(int tileCount, int displayW, int contentH, int* outCols, int* outRows) {
|
static void calculateGrid(
|
||||||
|
int tileCount, int displayW, int contentH, int* outCols, int* outRows) {
|
||||||
// Calculate aspect ratio to determine preferred layout
|
// Calculate aspect ratio to determine preferred layout
|
||||||
float aspectRatio = (float)displayW / contentH;
|
float aspectRatio = (float)displayW / contentH;
|
||||||
|
|
||||||
// Start with simple square-ish grid
|
// Start with simple square-ish grid
|
||||||
int cols = (int)std::sqrt(tileCount * aspectRatio);
|
int cols = (int)std::sqrt(tileCount * aspectRatio);
|
||||||
if(cols < 1) cols = 1;
|
if(cols < 1)
|
||||||
if(cols > tileCount) cols = tileCount;
|
cols = 1;
|
||||||
|
if(cols > tileCount)
|
||||||
|
cols = tileCount;
|
||||||
|
|
||||||
int rows = (tileCount + cols - 1) / cols;
|
int rows = (tileCount + cols - 1) / cols;
|
||||||
|
|
||||||
// For wide displays (landscape), prefer more columns
|
// For wide displays (landscape), prefer more columns
|
||||||
if(aspectRatio > 1.5f && tileCount <= 6) {
|
if(aspectRatio > 1.5f && tileCount <= 6) {
|
||||||
cols = tileCount;
|
cols = tileCount;
|
||||||
@@ -82,21 +81,22 @@ private:
|
|||||||
rows = tileCount;
|
rows = tileCount;
|
||||||
cols = 1;
|
cols = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*outCols = cols;
|
*outCols = cols;
|
||||||
*outRows = rows;
|
*outRows = rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find next available grid position
|
/// Find next available grid position
|
||||||
static void findNextPosition(const TileLayout* layouts, int count, int gridCols, int gridRows, int* outCol, int* outRow) {
|
static void findNextPosition(const TileLayout* layouts, int count, int gridCols, int gridRows,
|
||||||
|
int* outCol, int* outRow) {
|
||||||
// Simple: find first empty cell
|
// Simple: find first empty cell
|
||||||
// Could be enhanced to pack tightly based on tile sizes
|
// Could be enhanced to pack tightly based on tile sizes
|
||||||
for(int r = 0; r < gridRows; r++) {
|
for(int r = 0; r < gridRows; r++) {
|
||||||
for(int c = 0; c < gridCols; c++) {
|
for(int c = 0; c < gridCols; c++) {
|
||||||
bool occupied = false;
|
bool occupied = false;
|
||||||
for(int i = 0; i < count; i++) {
|
for(int i = 0; i < count; i++) {
|
||||||
if(layouts[i].col <= c && c < layouts[i].col + layouts[i].cols &&
|
if(layouts[i].col <= c && c < layouts[i].col + layouts[i].cols
|
||||||
layouts[i].row <= r && r < layouts[i].row + layouts[i].rows) {
|
&& layouts[i].row <= r && r < layouts[i].row + layouts[i].rows) {
|
||||||
occupied = true;
|
occupied = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void render(const ScreenState& st) {
|
void render(const ScreenState& st) {
|
||||||
if(!_drv) return;
|
if(!_drv)
|
||||||
|
return;
|
||||||
_drv->render(st);
|
_drv->render(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,62 +147,65 @@ public:
|
|||||||
/// Show touch feedback - highlights the tile at given coordinates
|
/// Show touch feedback - highlights the tile at given coordinates
|
||||||
/// Returns true if a valid tile is being touched
|
/// Returns true if a valid tile is being touched
|
||||||
bool showTouchFeedback(int x, int y) {
|
bool showTouchFeedback(int x, int y) {
|
||||||
if(!_drv || _gridCols <= 0) return false;
|
if(!_drv || _gridCols <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Transform touch coordinates
|
// Transform touch coordinates
|
||||||
_drv->transformTouch(&x, &y);
|
_drv->transformTouch(&x, &y);
|
||||||
|
|
||||||
int headerH = 30;
|
int headerH = 30;
|
||||||
if(y < headerH) return false;
|
if(y < headerH)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Calculate which cell
|
// Calculate which cell
|
||||||
int cellW = _drv->width() / _gridCols;
|
int cellW = _drv->width() / _gridCols;
|
||||||
int cellH = (_drv->height() - headerH) / _gridRows;
|
int cellH = (_drv->height() - headerH) / _gridRows;
|
||||||
|
|
||||||
int col = x / cellW;
|
int col = x / cellW;
|
||||||
int row = (y - headerH) / cellH;
|
int row = (y - headerH) / cellH;
|
||||||
|
|
||||||
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows)
|
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Find which tile is at this position
|
// Find which tile is at this position
|
||||||
for(int i = 0; i < _tileCount; i++) {
|
for(int i = 0; i < _tileCount; i++) {
|
||||||
const TileLayout& lay = _layouts[i];
|
const TileLayout& lay = _layouts[i];
|
||||||
if(lay.col <= col && col < lay.col + lay.cols &&
|
if(lay.col <= col && col < lay.col + lay.cols && lay.row <= row
|
||||||
lay.row <= row && lay.row + lay.rows > row) {
|
&& lay.row + lay.rows > row) {
|
||||||
// Found the tile - draw highlight via driver
|
// Found the tile - draw highlight via driver
|
||||||
_drv->updateHint(lay.x, lay.y, true); // active=true means show feedback
|
_drv->updateHint(lay.x, lay.y, true); // active=true means show feedback
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear touch feedback
|
/// Clear touch feedback
|
||||||
void clearTouchFeedback() {
|
void clearTouchFeedback() {
|
||||||
if(_drv)
|
if(_drv)
|
||||||
_drv->updateHint(0, 0, false); // active=false means clear
|
_drv->updateHint(0, 0, false); // active=false means clear
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if current position is still in same tile as touch-down
|
/// Check if current position is still in same tile as touch-down
|
||||||
bool isSameTile(int downX, int downY, int currentX, int currentY) const {
|
bool isSameTile(int downX, int downY, int currentX, int currentY) const {
|
||||||
if(!_drv || _gridCols <= 0 || downX < 0) return false;
|
if(!_drv || _gridCols <= 0 || downX < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
int dx = downX, dy = downY;
|
int dx = downX, dy = downY;
|
||||||
int cx = currentX, cy = currentY;
|
int cx = currentX, cy = currentY;
|
||||||
|
|
||||||
_drv->transformTouch(&dx, &dy);
|
_drv->transformTouch(&dx, &dy);
|
||||||
_drv->transformTouch(&cx, &cy);
|
_drv->transformTouch(&cx, &cy);
|
||||||
|
|
||||||
int headerH = 30;
|
int headerH = 30;
|
||||||
int cellW = _drv->width() / _gridCols;
|
int cellW = _drv->width() / _gridCols;
|
||||||
int cellH = (_drv->height() - headerH) / _gridRows;
|
int cellH = (_drv->height() - headerH) / _gridRows;
|
||||||
|
|
||||||
int downCol = dx / cellW;
|
int downCol = dx / cellW;
|
||||||
int downRow = (dy - headerH) / cellH;
|
int downRow = (dy - headerH) / cellH;
|
||||||
int curCol = cx / cellW;
|
int curCol = cx / cellW;
|
||||||
int curRow = (cy - headerH) / cellH;
|
int curRow = (cy - headerH) / cellH;
|
||||||
|
|
||||||
return downCol == curCol && downRow == curRow;
|
return downCol == curCol && downRow == curRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,59 +214,55 @@ public:
|
|||||||
|
|
||||||
/// Handle dashboard touch - returns action for tapped tile, or NONE
|
/// Handle dashboard touch - returns action for tapped tile, or NONE
|
||||||
TileAction handleDashboardTouch(int x, int y) const {
|
TileAction handleDashboardTouch(int x, int y) const {
|
||||||
if(!_drv || _gridCols <= 0) return TileAction::NONE;
|
if(!_drv || _gridCols <= 0)
|
||||||
|
return TileAction::NONE;
|
||||||
|
|
||||||
// Transform touch coordinates (handles rotated touch panels)
|
// Transform touch coordinates (handles rotated touch panels)
|
||||||
_drv->transformTouch(&x, &y);
|
_drv->transformTouch(&x, &y);
|
||||||
|
|
||||||
int dispW = _drv->width();
|
int dispW = _drv->width();
|
||||||
int dispH = _drv->height();
|
int dispH = _drv->height();
|
||||||
int headerH = 30;
|
int headerH = 30;
|
||||||
|
|
||||||
// Check if in header area
|
// Check if in header area
|
||||||
if(y < headerH) return TileAction::NONE;
|
if(y < headerH)
|
||||||
|
return TileAction::NONE;
|
||||||
|
|
||||||
// Calculate which tile was touched using grid
|
// Calculate which tile was touched using grid
|
||||||
int cellW = dispW / _gridCols;
|
int cellW = dispW / _gridCols;
|
||||||
int cellH = (dispH - headerH) / _gridRows;
|
int cellH = (dispH - headerH) / _gridRows;
|
||||||
|
|
||||||
int col = x / cellW;
|
int col = x / cellW;
|
||||||
int row = (y - headerH) / cellH;
|
int row = (y - headerH) / cellH;
|
||||||
|
|
||||||
// Bounds check
|
// Bounds check
|
||||||
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows) {
|
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows) {
|
||||||
return TileAction::NONE;
|
return TileAction::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find which tile occupies this cell
|
// Find which tile occupies this cell
|
||||||
for(int i = 0; i < _tileCount; i++) {
|
for(int i = 0; i < _tileCount; i++) {
|
||||||
const TileLayout& layout = _layouts[i];
|
const TileLayout& layout = _layouts[i];
|
||||||
if(layout.col <= col && col < layout.col + layout.cols &&
|
if(layout.col <= col && col < layout.col + layout.cols && layout.row <= row
|
||||||
layout.row <= row && row < layout.row + layout.rows) {
|
&& row < layout.row + layout.rows) {
|
||||||
return DASHBOARD_TILES[i].action;
|
return DASHBOARD_TILES[i].action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TileAction::NONE;
|
return TileAction::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate and store layouts for dashboard tiles
|
/// Calculate and store layouts for dashboard tiles
|
||||||
/// Called by drivers who want to use the layout helper
|
/// Called by drivers who want to use the layout helper
|
||||||
int calculateDashboardLayouts(int headerH = 30, int margin = 8) {
|
int calculateDashboardLayouts(int headerH = 30, int margin = 8) {
|
||||||
if(!_drv) return 0;
|
if(!_drv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
_tileCount = TileLayoutHelper::calculateLayouts(
|
_tileCount = TileLayoutHelper::calculateLayouts(
|
||||||
_drv->width(),
|
_drv->width(), _drv->height(), headerH, margin, _layouts, &_gridCols, &_gridRows);
|
||||||
_drv->height(),
|
|
||||||
headerH,
|
|
||||||
margin,
|
|
||||||
_layouts,
|
|
||||||
&_gridCols,
|
|
||||||
&_gridRows
|
|
||||||
);
|
|
||||||
return _tileCount;
|
return _tileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get calculated layout for a specific tile
|
/// Get calculated layout for a specific tile
|
||||||
const TileLayout* getTileLayouts() const { return _layouts; }
|
const TileLayout* getTileLayouts() const { return _layouts; }
|
||||||
int getGridCols() const { return _gridCols; }
|
int getGridCols() const { return _gridCols; }
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ void DoorbellLogic::update() {
|
|||||||
default:
|
default:
|
||||||
// Inactivity timeout: turn off screen after no activity
|
// Inactivity timeout: turn off screen after no activity
|
||||||
if(_state.screen != ScreenID::OFF && now - _lastActivityMs > INACTIVITY_TIMEOUT_MS) {
|
if(_state.screen != ScreenID::OFF && now - _lastActivityMs > INACTIVITY_TIMEOUT_MS) {
|
||||||
Serial.printf("[%lu] [STATE] Inactivity timeout (%lu ms) → OFF\n",
|
Serial.printf("[%lu] [STATE] Inactivity timeout (%lu ms) → OFF\n", millis(),
|
||||||
millis(), now - _lastActivityMs);
|
now - _lastActivityMs);
|
||||||
_state.screen = ScreenID::OFF;
|
_state.screen = ScreenID::OFF;
|
||||||
_display->setBacklight(false);
|
_display->setBacklight(false);
|
||||||
_state.backlightOn = false;
|
_state.backlightOn = false;
|
||||||
@@ -231,13 +231,13 @@ void DoorbellLogic::onAdmin(const String& cmd) {
|
|||||||
ESP.restart();
|
ESP.restart();
|
||||||
} else if(cmd == "dashboard") {
|
} else if(cmd == "dashboard") {
|
||||||
Serial.printf("[%lu] [ADMIN] dashboard\n", millis());
|
Serial.printf("[%lu] [ADMIN] dashboard\n", millis());
|
||||||
_lastActivityMs = millis(); // Reset inactivity timer
|
_lastActivityMs = millis(); // Reset inactivity timer
|
||||||
_state.screen = ScreenID::DASHBOARD;
|
_state.screen = ScreenID::DASHBOARD;
|
||||||
_display->setBacklight(true);
|
_display->setBacklight(true);
|
||||||
_state.backlightOn = true;
|
_state.backlightOn = true;
|
||||||
} else if(cmd == "off") {
|
} else if(cmd == "off") {
|
||||||
Serial.printf("[%lu] [ADMIN] off\n", millis());
|
Serial.printf("[%lu] [ADMIN] off\n", millis());
|
||||||
_lastActivityMs = millis(); // Reset inactivity timer
|
_lastActivityMs = millis(); // Reset inactivity timer
|
||||||
_state.screen = ScreenID::OFF;
|
_state.screen = ScreenID::OFF;
|
||||||
_display->setBacklight(false);
|
_display->setBacklight(false);
|
||||||
_state.backlightOn = false;
|
_state.backlightOn = false;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
#include "ScreenState.h"
|
#include "ScreenState.h"
|
||||||
|
|
||||||
struct TouchEvent {
|
struct TouchEvent {
|
||||||
bool pressed = false; // finger just touched down
|
bool pressed = false; // finger just touched down
|
||||||
bool released = false; // finger just lifted (after being pressed)
|
bool released = false; // finger just lifted (after being pressed)
|
||||||
int x = 0; // current x position
|
int x = 0; // current x position
|
||||||
int y = 0; // current y position
|
int y = 0; // current y position
|
||||||
int downX = -1; // x position where touch started
|
int downX = -1; // x position where touch started
|
||||||
int downY = -1; // y position where touch started
|
int downY = -1; // y position where touch started
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HoldState {
|
struct HoldState {
|
||||||
|
|||||||
@@ -10,24 +10,24 @@ enum class BootStage { SPLASH, INIT_DISPLAY, INIT_NETWORK, CONNECTING_WIFI, READ
|
|||||||
/// Dashboard tile action handlers
|
/// Dashboard tile action handlers
|
||||||
enum class TileAction {
|
enum class TileAction {
|
||||||
NONE,
|
NONE,
|
||||||
ALERT, // Trigger alert
|
ALERT, // Trigger alert
|
||||||
SILENCE, // Silence alert
|
SILENCE, // Silence alert
|
||||||
STATUS, // Send heartbeat/status
|
STATUS, // Send heartbeat/status
|
||||||
REBOOT, // Reboot device
|
REBOOT, // Reboot device
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Dashboard tile layout constraints for flexible grid
|
/// Dashboard tile layout constraints for flexible grid
|
||||||
struct TileConstraint {
|
struct TileConstraint {
|
||||||
uint8_t minCols = 1; // minimum columns this tile needs
|
uint8_t minCols = 1; // minimum columns this tile needs
|
||||||
uint8_t minRows = 1; // minimum rows this tile needs
|
uint8_t minRows = 1; // minimum rows this tile needs
|
||||||
uint8_t weight = 1; // priority for growing/shrinking (higher = more flexible)
|
uint8_t weight = 1; // priority for growing/shrinking (higher = more flexible)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Computed tile position in the grid
|
/// Computed tile position in the grid
|
||||||
struct TileLayout {
|
struct TileLayout {
|
||||||
int x, y; // pixel position
|
int x, y; // pixel position
|
||||||
int w, h; // pixel size
|
int w, h; // pixel size
|
||||||
int col, row; // grid position
|
int col, row; // grid position
|
||||||
int cols, rows; // grid span
|
int cols, rows; // grid span
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,10 +41,10 @@ struct DashboardTile {
|
|||||||
|
|
||||||
/// Standard dashboard tiles (auto-gridded based on count and constraints)
|
/// Standard dashboard tiles (auto-gridded based on count and constraints)
|
||||||
static constexpr DashboardTile DASHBOARD_TILES[] = {
|
static constexpr DashboardTile DASHBOARD_TILES[] = {
|
||||||
{ "Alert", 0x0280, TileAction::ALERT, {1, 1, 1} },
|
{ "Alert", 0x0280, TileAction::ALERT, { 1, 1, 1 } },
|
||||||
{ "Silent", 0x0400, TileAction::SILENCE, {1, 1, 1} },
|
{ "Silent", 0x0400, TileAction::SILENCE, { 1, 1, 1 } },
|
||||||
{ "Status", 0x0440, TileAction::STATUS, {1, 1, 1} },
|
{ "Status", 0x0440, TileAction::STATUS, { 1, 1, 1 } },
|
||||||
{ "Reboot", 0x0100, TileAction::REBOOT, {1, 1, 1} },
|
{ "Reboot", 0x0100, TileAction::REBOOT, { 1, 1, 1 } },
|
||||||
};
|
};
|
||||||
static constexpr int DASHBOARD_TILE_COUNT = sizeof(DASHBOARD_TILES) / sizeof(DASHBOARD_TILES[0]);
|
static constexpr int DASHBOARD_TILE_COUNT = sizeof(DASHBOARD_TILES) / sizeof(DASHBOARD_TILES[0]);
|
||||||
|
|
||||||
|
|||||||
32
mise.toml
32
mise.toml
@@ -28,27 +28,7 @@ arduino-cli compile --fqbn "$FQBN" --libraries ./libraries $LIBS --build-propert
|
|||||||
[tasks.upload]
|
[tasks.upload]
|
||||||
description = "Upload (uses BOARD env var)"
|
description = "Upload (uses BOARD env var)"
|
||||||
depends = ["compile"]
|
depends = ["compile"]
|
||||||
run = """
|
run = "source ./boards/$BOARD/board-config.sh && arduino-cli upload --fqbn $FQBN --port $PORT ./boards/$BOARD"
|
||||||
# Kill any processes using the serial port first
|
|
||||||
source ./boards/$BOARD/board-config.sh
|
|
||||||
PORT="${PORT:-$PORT}"
|
|
||||||
fuser -k "$PORT" 2>/dev/null || true
|
|
||||||
for pid in $(pgrep -f "monitor-agent.py" 2>/dev/null || true); do
|
|
||||||
kill "$pid" 2>/dev/null || true
|
|
||||||
done
|
|
||||||
rm -f "/tmp/doorbell-${BOARD}.lock" 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
source ./scripts/lockfile.sh
|
|
||||||
|
|
||||||
FORCE=1 TASK_NAME=upload acquire_lock || exit 1
|
|
||||||
|
|
||||||
arduino-cli upload --fqbn "$FQBN" --port "$PORT" ./boards/$BOARD
|
|
||||||
|
|
||||||
# Restart monitor in background
|
|
||||||
python3 ./scripts/monitor-agent.py "$BOARD" &
|
|
||||||
echo "[OK] Monitor restarted in background"
|
|
||||||
"""
|
|
||||||
|
|
||||||
[tasks.monitor-raw]
|
[tasks.monitor-raw]
|
||||||
run = """
|
run = """
|
||||||
@@ -80,15 +60,15 @@ set +e
|
|||||||
# Kill any processes using the serial port
|
# Kill any processes using the serial port
|
||||||
source ./boards/$BOARD/board-config.sh
|
source ./boards/$BOARD/board-config.sh
|
||||||
PORT="${PORT:-$PORT}"
|
PORT="${PORT:-$PORT}"
|
||||||
fuser -k "$PORT" 2>/dev/null
|
fuser -k "$PORT" 2>/dev/null || true
|
||||||
|
|
||||||
# Kill monitor-agent processes for this board
|
# Kill monitor-agent processes for this board
|
||||||
for pid in $(pgrep -f "monitor-agent.py"); do
|
for pid in $(pgrep -f "monitor-agent.py" 2>/dev/null || true); do
|
||||||
kill "$pid" 2>/dev/null
|
kill "$pid" 2>/dev/null || true
|
||||||
done
|
done
|
||||||
|
|
||||||
# Also clean up lockfile
|
# Also clean up lockfile
|
||||||
rm -f "/tmp/doorbell-${BOARD}.lock" 2>/dev/null
|
rm -f "/tmp/doorbell-${BOARD}.lock" 2>/dev/null || true
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
echo "[OK] Killed processes for $BOARD"
|
echo "[OK] Killed processes for $BOARD"
|
||||||
@@ -224,4 +204,4 @@ echo "[OK] Generated .crush.json with FQBN: $FQBN"
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
BOARD = "esp32-32e-4"
|
BOARD = "esp32-s3-lcd-43"
|
||||||
|
|||||||
1
vendor/esp32-s3-lcd-43/LovyanGFX
vendored
1
vendor/esp32-s3-lcd-43/LovyanGFX
vendored
Submodule vendor/esp32-s3-lcd-43/LovyanGFX deleted from 42998359d8
Reference in New Issue
Block a user