Path:
C:\GitHub\XNODE
Purpose:
Gen1stays frozen as the old baseline.Gen2stays frozen as the first Meshtastic snapshot.Gen3was the active LilyGO T-Watch S3 / XNODE working tree before migration into git.
Archive paths:
C:\GitHub\XNODE\obsolete\backup\My-TTGO-Watch-Gen1C:\GitHub\XNODE\obsolete\backup\My-TTGO-Watch-Gen2C:\GitHub\XNODE\obsolete\backup\My-TTGO-Watch-Gen3
Current rule:
- All active development now happens in
C:\GitHub\XNODE.
Working now in C:\GitHub\XNODE:
- Firmware builds and flashes on the LilyGO Watch Gen3 (
t-watch2020-v3-s3). - XNODE can install one basemap tile into watch flash at
/spiffs/osmmap/<z>/<x>/<y>.png. - The watch stores the basemap center lon/lat/zoom in
osmmap.json. offline from watch flashloads that installed tile and keeps using the same image at every watch zoom.- Zoom buttons scale the image in place instead of switching to some stale tile from another zoom.
- Marker placement uses Web Mercator math, so the watch position and external markers stay aligned as the image zoom changes.
- Meshtastic text and position handling still work.
Known limitations:
- Watch-flash mode is a fixed single-tile basemap, not a full slippy multi-tile map engine.
- SPIFFS is small, so the installed tile needs to stay compact. Host-side tooling downsizes PNGs when needed.
- Old tiles can still exist in SPIFFS, but the watch now follows the persisted installed tile instead of bouncing to unrelated images.
The broken behavior came from two separate problems:
- XNODE tile upload wrote files without reliably creating
/spiffs/osmmap/<z>/<x>. - The watch map app still treated watch flash like a normal slippy source, so changing zoom could jump to older tiles already in flash.
The fix in this repo is:
src/hardware/ble/xnode.cpp- accepts
mapTileuploads only under/spiffs/osmmap - creates
/spiffs/osmmap/<z>/<x>before writing - writes uploaded PNG chunks into the final watch-flash tile path
- accepts
src/app/osmmap/config/osmmap_config.cppsrc/app/osmmap/config/osmmap_config.h- persist the installed watch-flash basemap center and zoom
src/app/osmmap/osmmap_app_main.cppoffline from watch flashnow resolves to the installed center tile path- watch zoom changes scale the LVGL image instead of requesting a different
$z/$x/$y
src/utils/osm_map/osm_map.cpp- marker projection now uses proper Web Mercator pixel math
- fixed the tile longitude helper bug so marker placement stays consistent
The host apps now use the same simple install path:
- Pick a center point, currently from browser GPS.
- Fetch one raster tile for that center and zoom.
- Compact the PNG if needed.
- Send it over XNODE as
mapTileto:
/spiffs/osmmap/<z>/<x>/<y>.png
- Send
installBasemapwith the manifest center lon/lat/zoom. - The watch switches to
offline from watch flash.
After that:
- zoom in/out scales the installed image
- markers stay in the correct place on that image
- the watch no longer flips between unrelated old zoom tiles
Working now:
XTOC/xtoc-web/src/pages/XnodePage.tsxcan load one tile from the active raster template and install it on the watch.xcom/xcom/modules/xnode/xnode.jscan do the same thing.- Both host apps use the XNODE bridge
mapTileupload plusinstallBasemapmanifest flow.
Relevant host-side files:
C:\GitHub\XTOC\xtoc-web\src\core\xnodeBridge.tsC:\GitHub\XTOC\xtoc-web\src\pages\XnodePage.tsxC:\GitHub\xcom\xcom\modules\shared\xnode\xnodeBridge.jsC:\GitHub\xcom\xcom\modules\xnode\xnode.js
Hardware:
- LilyGO T-Watch S3 / T-Watch 2020 form factor
- ESP32-S3
- 16 MB flash
- 8 MB PSRAM
- SX1262 LoRa
PlatformIO environment:
t-watch2020-v3-s3
Last confirmed USB port:
COM8USB Serial DeviceUSB\\VID_303A&PID_1001&MI_00
pio run -e t-watch2020-v3-s3Normal path:
pio run -e t-watch2020-v3-s3 -t upload --upload-port COM8That was the path used for the flashed XNODE basemap fix.
Check the port first:
Get-CimInstance Win32_SerialPort | Select-Object DeviceID, Description, PNPDeviceIDDirect esptool.py fallback:
python C:\Users\Eric\.platformio\packages\tool-esptoolpy\esptool.py --chip esp32s3 --port COM8 --baud 460800 write_flash -z --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 .pio\build\t-watch2020-v3-s3\bootloader.bin 0x8000 .pio\build\t-watch2020-v3-s3\partitions.bin 0xE000 C:\Users\Eric\.platformio\packages\framework-arduinoespressif32@3.20009.0\tools\partitions\boot_app0.bin 0x10000 .pio\build\t-watch2020-v3-s3\firmware.binIf auto-reset fails:
- Put the watch into boot mode manually.
- Re-run the upload command on the new COM port if it changed.
Recovery note:
https://flasher.meshtastic.org/can recover the ESP32-S3 if needed.- That restores Meshtastic firmware, not this watch UI firmware.
After flashing:
- Open XTOC or XCOM.
- Open the
XNODEpage. - Connect to the watch.
- Press
Load map. - Press
Install map on watch. - On the watch, open the map app and select
offline from watch flashif it is not already active. - Press watch zoom in/out and confirm the same image scales while the marker stays aligned.