Skip to content

T-Deck LXMF Messenger v1.1.0

Choose a tag to compare

@varna9000 varna9000 released this 25 Jul 17:57

T-Deck LXMF Messenger v1.1.0

Single-flash firmware image for the LilyGO T-Deck v1. Everything is in the one file — no additional uploads needed.

Forty commits since v1.0.0. The headline additions are two entirely new tabs, voice messaging, and a run of µReticulum transport fixes that made opportunistic delivery work for the first time.

New

  • NomadNet page browser (NET tab) — fetch and render micron (.mu) pages from NomadNet nodes over LoRa or TCP, with colours, headings and clickable links.
  • rnsh shell client (SSH tab) — interactive shell against rnsh listeners over Reticulum Link + Channel. The terminal composites rows into a framebuf rather than issuing an SPI transaction per glyph, giving up to 80×32 on a 320px panel and still repainting faster than the 40×12 screen it replaced.
  • Voice messages — record with the mic key, encoded Codec2 3200 bps and sent as LXMF FIELD_AUDIO, interoperable with MeshChat and Sideband. Getting Codec2 encoding to work on ESP32 needed a full double-precision LPC/LSP pipeline — single-precision finds 0 of 10 LSP roots and outputs silence.
  • Cyrillic display support — CP866-layout font with glyph transcoding.
  • Mesh clock, per-peer routes, ping, and a live radio/mesh stats page in settings.
  • Keyboard backlight toggle (needs keyboard MCU firmware from 2024-12-25 or newer).

Fixed

  • Opportunistic (single-packet) messaging never worked between direct-range nodes. The packet builder wrapped direct sends in a transport header addressed "via" the destination itself, so every correct receiver silently discarded them as another relay's traffic. Link-based delivery worked throughout, which disguised this as RF trouble for weeks.
  • Attachments arrived looking like plain text. An image sent with a caption showed no marker and no clue the row was clickable; a JPEG from MeshChat was dropped outright, because MeshChat labels images by MIME subtype ("jpeg") and the receive path only accepted "jpg". Format now comes from the payload's magic bytes, markers lead the caption, file attachments are listed and playable/viewable where possible, and anything undecodable still says what it is rather than vanishing.
  • Message identity under history trim. Messages were tracked by list position, so once a chat hit its 30-message cap every later message collapsed onto the same index: delivery ticks landed on the wrong row and image clicks opened the wrong picture.
  • Half-duplex link establishment (LRRTT resend + DIRECT delivery retry) and outgoing-resource watchdog — unanswered advertisements retry, stalled transfers fail cleanly instead of wedging the link.
  • WiFi failures surface in the UI, and a failed scan can no longer take LoRa down with it.

Changed

  • Firmware layout. The five natmods (ed25519, bz2, codec2, tjpgd, webp) are now built into the app image as C modules, executing from flash instead of competing for internal IRAM. The factory partition grew 2 MB → 3 MB and the filesystem shrank 6 MB → 5 MB, so this is not an in-place upgrade from v1.0.0 — the partition table moved.
  • The system font is Spleen 8×16 (BSD-2) rather than the 1981 VGA ROM font.
  • WiFi/LWIP buffers moved to PSRAM.

First boot

The image carries no identity or configuration of its own — just main.py, tdeck_config.py and logo.jpg. On first boot each device creates /rns, generates its own X25519 + Ed25519 keypair, and names itself T-Deck-XXXX from the last four hex digits of its WiFi MAC, so a batch of freshly flashed devices are distinguishable in each other's node lists instead of all announcing as "T-Deck". Rename it from Settings at any time; that persists and overrides the default.

Serial logging is off by default (DEBUG = 0 in tdeck_config.py). Set it to 1 for app messages or 2 for the full Reticulum debug log when something needs investigating.

What's included

  • MicroPython v1.24.1 for ESP32-S3 with Octal SPIRAM
  • ST7789 C display driver (DMA-accelerated, Russ Hughes st7789_mpy)
  • Frozen in ROM: UI, sound, ES7210 mic driver, NomadNet browser, rnsh client, fonts, full µReticulum stack
  • Built into the app image: ed25519, bz2, codec2, tjpgd, webp
  • On the filesystem: main.py, tdeck_config.py, logo.jpg

Flashing

Requirements: esptool (pip install esptool)

1. Enter download mode:
Short GPIO0 to GND while pressing the reset button on the T-Deck, then release both. On the T-Deck, GPIO0 is the trackball click — hold the trackball down, tap reset, release.

2. Flash:

esptool --chip esp32s3 --port PORT erase-flash
esptool --chip esp32s3 --port PORT write-flash 0x0 tdeck_firmware.bin

Replace PORT with your serial port:

  • macOS: /dev/cu.usbmodem*
  • Linux: /dev/ttyACM0 or /dev/ttyUSB0
  • Windows: COM3 (check Device Manager)

Upgrading from v1.0.0: this rewrites the whole flash, including the filesystem — your node identity at /rns/identity goes with it and your LXMF address will change. Back it up first (mpremote cp -r :rns ./rns-backup) and copy it back after flashing if you want to keep your address.

Building it yourself

pip install esptool littlefs-python
cd tools && bash build_firmware.sh

Produces tools/firmware_build/tdeck_firmware.bin. First build takes ~20 minutes (clones ESP-IDF v5.2.3, MicroPython v1.24.1 and st7789_mpy, installs the Xtensa toolchain); rebuilds take ~30 seconds.