tdpro - improved cpu usage for maps and increased key responsiveness after boot; updated firmware date and build

This commit is contained in:
pelgraine
2026-03-17 15:46:42 +11:00
parent 4004acf15d
commit 33a3352692
3 changed files with 67 additions and 35 deletions

View File

@@ -8,11 +8,11 @@
#define FIRMWARE_VER_CODE 10
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "15 March 2026"
#define FIRMWARE_BUILD_DATE "17 March 2026"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "Meck v1.1"
#define FIRMWARE_VERSION "Meck v1.2"
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)

View File

@@ -1122,9 +1122,10 @@ void setup() {
if (ssid.length() > 0) {
MESH_DEBUG_PRINTLN("setup() - WiFi: connecting to '%s'", ssid.c_str());
WiFi.begin(ssid.c_str(), pass.c_str());
unsigned long timeout = millis() + 8000;
unsigned long timeout = millis() + 3000; // 3s max — non-critical, Settings can retry
while (WiFi.status() != WL_CONNECTED && millis() < timeout) {
delay(100);
yield(); // Feed WDT during wait
delay(50);
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("WiFi companion: connected to %s, IP: %s\n",
@@ -1415,20 +1416,20 @@ void loop() {
sensors.loop();
// GPS diagnostic — print sentence count every 30s so we can tell if Serial2 is receiving data
#if HAS_GPS
{
static unsigned long lastGpsDiag = 0;
if (millis() - lastGpsDiag >= 30000) {
lastGpsDiag = millis();
uint32_t sentences = gpsStream.getSentenceCount();
uint16_t perSec = gpsStream.getSentencesPerSec();
Serial.printf("GPS diag: %lu sentences total, %u/sec, Serial2.available=%d, lat=%.6f lon=%.6f\n",
(unsigned long)sentences, perSec, Serial2.available(),
sensors.node_lat, sensors.node_lon);
}
}
#endif
// GPS diagnostic — disabled to reduce serial noise (uncomment for debugging)
// #if HAS_GPS
// {
// static unsigned long lastGpsDiag = 0;
// if (millis() - lastGpsDiag >= 30000) {
// lastGpsDiag = millis();
// uint32_t sentences = gpsStream.getSentenceCount();
// uint16_t perSec = gpsStream.getSentencesPerSec();
// Serial.printf("GPS diag: %lu sentences total, %u/sec, Serial2.available=%d, lat=%.6f lon=%.6f\n",
// (unsigned long)sentences, perSec, Serial2.available(),
// sensors.node_lat, sensors.node_lon);
// }
// }
// #endif
// Map screen: periodically update own GPS position and contact markers
#if HAS_GPS
@@ -2492,6 +2493,7 @@ void handleKeyboardInput() {
ui_task.injectKey('g'); // Re-center on GPS
} else {
Serial.println("Opening map");
cpuPower.setBoost(); // Map render is CPU-intensive (PNG decode + SD reads)
{
MapScreen* ms = (MapScreen*)ui_task.getMapScreen();
if (ms) {
@@ -2509,7 +2511,7 @@ void handleKeyboardInput() {
double lon = ((double)ci.gps_lon) / 1000000.0;
ms->addMarker(lat, lon, ci.name, ci.type);
markerCount++;
Serial.printf(" marker: %s @ %.4f,%.4f (type=%d)\n", ci.name, lat, lon, ci.type);
// Serial.printf(" marker: %s @ %.4f,%.4f (type=%d)\n", ci.name, lat, lon, ci.type);
}
}
Serial.printf("MapScreen: %d contacts with GPS position\n", markerCount);

View File

@@ -137,22 +137,18 @@ public:
_zoomMin(MAP_MIN_ZOOM),
_zoomMax(MAP_MAX_ZOOM),
_pngBuf(nullptr),
_lineBuf(nullptr),
_tileFound(false)
{
// Allocate marker array in PSRAM at construction (~20KB)
// so addMarker() works before enter() is called
_markers = (MapMarker*)ps_calloc(MAP_MAX_MARKERS, sizeof(MapMarker));
if (_markers) {
Serial.printf("MapScreen: markers allocated (%d × %d = %d bytes PSRAM)\n",
MAP_MAX_MARKERS, (int)sizeof(MapMarker),
MAP_MAX_MARKERS * (int)sizeof(MapMarker));
} else {
Serial.println("MapScreen: marker PSRAM alloc FAILED");
}
// Marker array and PNG buffers are deferred to enter() to avoid
// consuming 20KB+ PSRAM at boot when the map may never be opened.
_markers = nullptr;
_numMarkers = 0;
}
~MapScreen() {
if (_pngBuf) { free(_pngBuf); _pngBuf = nullptr; }
if (_lineBuf) { free(_lineBuf); _lineBuf = nullptr; }
if (_markers) { free(_markers); _markers = nullptr; }
}
@@ -184,7 +180,12 @@ public:
// Add a location marker (call once per contact before entering map)
void clearMarkers() { _numMarkers = 0; }
void addMarker(double lat, double lon, const char* name = "", uint8_t type = 0) {
if (!_markers || _numMarkers >= MAP_MAX_MARKERS) return;
// Lazy-allocate markers on first use (deferred from constructor)
if (!_markers) {
_markers = (MapMarker*)ps_calloc(MAP_MAX_MARKERS, sizeof(MapMarker));
if (!_markers) return; // Alloc failed — skip silently
}
if (_numMarkers >= MAP_MAX_MARKERS) return;
if (lat == 0.0 && lon == 0.0) return; // Skip no-location contacts
_markers[_numMarkers].lat = lat;
_markers[_numMarkers].lon = lon;
@@ -203,6 +204,18 @@ public:
_einkDisplay = static_cast<GxEPDDisplay*>(&display);
_needsRedraw = true;
// Allocate marker array in PSRAM on first use (~20KB)
if (!_markers) {
_markers = (MapMarker*)ps_calloc(MAP_MAX_MARKERS, sizeof(MapMarker));
if (_markers) {
Serial.printf("MapScreen: markers allocated (%d × %d = %d bytes PSRAM)\n",
MAP_MAX_MARKERS, (int)sizeof(MapMarker),
MAP_MAX_MARKERS * (int)sizeof(MapMarker));
} else {
Serial.println("MapScreen: marker PSRAM alloc FAILED");
}
}
// Allocate PNG read buffer in PSRAM on first use
if (!_pngBuf) {
_pngBuf = (uint8_t*)ps_malloc(MAP_PNG_BUF_SIZE);
@@ -217,6 +230,20 @@ public:
}
}
// Allocate scanline decode buffer in PSRAM (512 bytes — avoids stack
// allocation inside the PNGdec callback which is called 256× per tile)
if (!_lineBuf) {
_lineBuf = (uint16_t*)ps_malloc(MAP_TILE_SIZE * sizeof(uint16_t));
if (!_lineBuf) {
_lineBuf = (uint16_t*)malloc(MAP_TILE_SIZE * sizeof(uint16_t));
}
if (_lineBuf) {
Serial.println("MapScreen: lineBuf allocated");
} else {
Serial.println("MapScreen: lineBuf alloc FAILED");
}
}
// Detect available zoom levels from SD card directories
detectZoomRange();
}
@@ -356,6 +383,7 @@ private:
// PNG decode buffer (PSRAM)
uint8_t* _pngBuf;
uint16_t* _lineBuf; // Scanline RGB565 buffer for PNG decode (PSRAM)
bool _tileFound; // Did last tile load succeed?
// PNGdec instance
@@ -381,6 +409,7 @@ private:
int offsetY; // Screen Y offset for this tile
int viewportY; // Top of viewport (MAP_VIEWPORT_Y)
int viewportH; // Height of viewport (MAP_VIEWPORT_H)
uint16_t* lineBuf; // Scanline decode buffer (PSRAM-allocated, avoids 512B stack usage per callback)
};
DrawContext _drawCtx;
@@ -487,7 +516,7 @@ private:
// Load a PNG tile from SD and decode it directly to the display
// screenX, screenY = top-left corner on display where this tile goes
bool loadAndRenderTile(int tileX, int tileY, int screenX, int screenY) {
if (!_pngBuf || !_einkDisplay) return false;
if (!_pngBuf || !_lineBuf || !_einkDisplay) return false;
char path[64];
buildTilePath(path, sizeof(path), _zoom, tileX, tileY);
@@ -521,6 +550,7 @@ private:
_drawCtx.offsetY = screenY;
_drawCtx.viewportY = MAP_VIEWPORT_Y;
_drawCtx.viewportH = MAP_VIEWPORT_H;
_drawCtx.lineBuf = _lineBuf;
// Open PNG from memory buffer
int rc = _png.openRAM(_pngBuf, fileSize, pngDrawCallback);
@@ -547,7 +577,7 @@ private:
// Uses getLineAsRGB565 with correct (little) endianness for ESP32.
static int pngDrawCallback(PNGDRAW* pDraw) {
DrawContext* ctx = (DrawContext*)pDraw->pUser;
if (!ctx || !ctx->display || !ctx->png) return 0;
if (!ctx || !ctx->display || !ctx->png || !ctx->lineBuf) return 0;
int screenY = ctx->offsetY + pDraw->y;
@@ -564,9 +594,8 @@ private:
}
uint16_t lineWidth = pDraw->iWidth;
uint16_t lineBuf[MAP_TILE_SIZE];
if (lineWidth > MAP_TILE_SIZE) lineWidth = MAP_TILE_SIZE;
ctx->png->getLineAsRGB565(pDraw, lineBuf, PNG_RGB565_LITTLE_ENDIAN, 0xFFFFFFFF);
ctx->png->getLineAsRGB565(pDraw, ctx->lineBuf, PNG_RGB565_LITTLE_ENDIAN, 0xFFFFFFFF);
for (int x = 0; x < lineWidth; x++) {
int screenX = ctx->offsetX + x;
@@ -574,7 +603,7 @@ private:
// RGB565 little-endian on ESP32: standard bit layout
// R[15:11] G[10:5] B[4:0]
uint16_t pixel = lineBuf[x];
uint16_t pixel = ctx->lineBuf[x];
// For B&W tiles this is 0x0000 (black) or 0xFFFF (white)
// Simple threshold on full 16-bit value handles both cleanly
@@ -639,6 +668,7 @@ private:
} else {
missing++;
}
yield(); // Feed WDT between tiles — each tile can take 1-2s at 80MHz
}
}