mirror of
https://github.com/pelgraine/Meck.git
synced 2026-03-28 17:42:44 +01:00
tdpro - improved cpu usage for maps and increased key responsiveness after boot; updated firmware date and build
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user