An alternative open-source firmware for the LilyGO T-Deck Pro
Music, audiobooks, eBooks and LoRa mesh chat โ in one handheld.
๐ฌ๐ง English ยท ๐ฉ๐ช Deutsch ยท ๐ธ๐ช Svenska
๐ fennek.dumke.me
Fennek turns the LilyGO T-Deck Pro (ESP32-S3, E-Ink, LoRa) into a real handheld: listen to music, resume audiobooks, read eBooks and chat over the LoRa mesh via MeshCore โ with a homescreen launcher, touch + physical keyboard, and background audio that keeps playing across app switches. Like the desert fox: small, frugal, big ears.
It is a standalone alternative to the factory firmware โ built around the hardware's defining quirk, that E-Ink, the SD card and LoRa all share one SPI bus, while still delivering stutter-free audio playback.
![]() Launcher (app picker) |
![]() Music โ playback |
![]() Games โ Tic-Tac-Toe |
![]() Settings (radio & system) |
![]() Standby (sleeping fennec) |
![]() Maps โ offline SD tiles + GPS |
Rendered pixel-accurately from the real drawing code (240ร320 E-Ink) via
tools/screenshots.sh โ see tools/.
| App | Features |
|---|---|
| ๐ต Music | MP3/AAC/FLAC/WAV from SD (/music), artist/album/playlist browser, ID3 tags (with SD cache), shuffle/repeat, sleep timer, resume after reboot |
| ๐ง Audiobook | Books as folders under /audiobooks, chapters natural-sorted, per-book bookmark (NVS), ยฑ30 s jumps, sleep timer |
| ๐ Reading | .txt and .epub from /books, on-device EPUB conversion (ROM-tinfl), page-index cache, per-book reading position |
| ๐ก Mesh | Lean MeshCore client: public and hashtag channels (#test โฆ), DMs with delivery status, contacts from adverts, message log on SD incl. history reload |
| ๐ฎ Games | 2048, Minesweeper, Chess (Negamax AI) and Tic-Tac-Toe โ logic host-tested |
| ๐ Notes | One note per day under /notes (YYYY-MM-DD.md); "+ Today" opens or appends to today's note, the list shows every day newest-first with a first-line preview, append-style editor with delete confirmation |
| ๐๏ธ Podcast | RSS subscriptions in /podcasts/feeds.txt (Freakshow preset), syncs the latest episode over Wi-Fi and keeps only that one โ downloaded to SD, played via the audio queue with resume |
| โ๏ธ Options | Radio presets (EU Narrow = DE/NRW standard 869.618 MHz / 62.5 kHz / SF8), individual parameters, node name, battery info, firmware version |
Plus: a status line (battery, playback), standby/key-lock via the button, and a
serial debug console over USB (type help โ status, chan test hello,
meshlog, ls /books โฆ).
LilyGO T-Deck Pro V1.1: ESP32-S3 (16 MB flash, 8 MB PSRAM), E-Ink GDEQ031T10 240ร320, CST328 touch (I2C), TCA8418 keyboard, PCM5102A DAC (I2S, 3.5 mm jack), SX1262 LoRa, BQ27220 fuel gauge, microSD.
Defining quirk: E-Ink, the SD card and LoRa share one SPI bus. The entire architecture revolves around audio never stuttering despite that, and inputs responding instantly โ details in
CLAUDE.md(anti-stutter invariants).
The T-Deck Pro has four awkward constraints; Fennek is the story of working with
them. (Full design notes and anti-stutter invariants in CLAUDE.md.)
- ๐ No real-time clock. There is no battery-backed RTC. The canonical clock is
the ESP32 system time (it survives deep sleep, unlike a
millis()clock), set in priority order from GPS โ NTP โ mesh adverts; drift is learned and a future-dated packet can't drag the clock forward unchecked. - ๐ Can't stay online. Always-on networking isn't possible on this power budget โ and Wi-Fi and audio can't run at once (the Wi-Fi task on core 0 evicts the audio task). So Fennek never holds a connection: scrobbles, note polishing and podcast downloads are batched into a short Wi-Fi window before standby, and unused peripherals (GPS, haptics) are powered down at boot.
- ๐งฉ Only two cores. Two cores mean barely any true multitasking. Audio decoding is pinned to core 0, the UI + mesh pump to core 1; SD library scans pause during playback and the chess AI runs at low priority โ so playback stays smooth and the keyboard responsive.
- ๐๏ธ E-Ink screen. E-Ink is beautiful but slow, and full refreshes flash the panel. Fennek redraws only on a real change, paints progress/status as narrow region strips instead of full repaints, and stretches the anti-ghosting full refresh out to keep the screen calm.
Prerequisite: PlatformIO. Connect the T-Deck Pro via USB-C, then:
pio run -e fennek # build
pio run -e fennek -t upload # flash (USB-C)
pio device monitor -b 115200 # log + debug consoleThe firmware also runs without an SD card (apps then show a hint). Radio parameters are configurable at runtime in the Options app; the default is the EU/UK Narrow preset commonly used in Germany.
โ ๏ธ Custom firmware replaces the factory software. You flash at your own risk โ a way back to the original firmware is available via the LilyGO resources.
src/โ active firmware (core/drivers & framework,services/audio/ library/text,apps/the apps)lib/meshcore/,lib/ed25519/โ vendored MeshCore stack (subset)boards/t-deck_pro.jsonโ board definition (partitiondefault_16MB.csv)CHANGELOG.mdโ release notesCLAUDE.mdโ architecture, invariants, verification statusLICENSEโ GPL-3.0-or-later
Fennek is licensed under the GNU General Public License v3.0 or later
(GPL-3.0-or-later) โ see LICENSE.
Bundled components keep their own GPL-compatible licenses:
- MeshCore (
lib/meshcore/) โ MIT License, ยฉ Scott Powell / rippleradios.com (original,lib/meshcore/LICENSE) - ed25519 (
lib/ed25519/) โ zlib License, ยฉ Orson Peters (lib/ed25519/license.txt)
Fennek started out inspired by the Meck fork
(pelgraine/Meck, a MeshCore companion for
the T-Deck), but was rebuilt from v1.0.0 as a standalone multi-app firmware and
has been its own project ever since. The mesh stack is based on
MeshCore by Scott Powell. The earlier
Meck code (formerly under archive_legacy/) lives in the Git history and can be
restored from there at any time.





