Meck-P4 v0.1 — First Pre-Release for the LilyGo T-Display P4
Pre-releaseThe first publicly flashable Meck firmware for the LilyGo T-Display P4. One
file, one offset, you're on the mesh.
⚠️ This is a pre-release, not a finished product. Many of the features people associate with Meck on the T-Deck Pro and T5S3 — direct messaging, roomserver access, repeater admin, trace route, web browser, IRC, audio player — are not yet implemented on the P4. What's here is the foundation: a fully functional MeshCore node with channel messaging, contacts, persistent storage, GPS, and battery monitoring. See the full feature list and roadmap.
Hardware
main/examples/lvgl_9_ui/main.cpp if you want to try it.
Flashing
Ensure you use the right-usb C port, ie not the high-speed charger port to flash.
The release file meck-p4-0.1-merged.bin is a merged binary containing the bootloader, partition table, and application combined into a single image — flash it at address 0x0.
Using the MeshCore Flasher (web-based):
- Go to https://flasher.meshcore.io
- Scroll to the bottom and select Custom Firmware
- Select the
meck-p4-0.1.binfile you downloaded - Click OK for the warning about erase files because it's a merged binary.
- Click Flash, choose your device in the popup, and click Connect
Using esptool.py:
pip install esptool
esptool.py --chip esp32p4 -p PORT write_flash 0x0 meck-p4-0.1.bin
(Replace PORT with /dev/cu.usbmodemXXXX on macOS, /dev/ttyACM0 on Linux, or COM3 on Windows.)
If you've previously had something else on the device, run esptool.py --chip esp32p4 -p PORT erase_flash first to clear NVS so Meck starts with clean defaults.
An SD card is recommended. With a FAT32-formatted card inserted, every saved setting and channel message is mirrored automatically. The device works without one but loses message history on reboot.
What's Working
📡 Mesh networking
- Channel messaging — send and receive on Public, #test, #sydney
- 17-preset radio picker (AU, US, EU, CN regions). Boots on Australia Narrow by default (916.575 MHz / SF7 / BW 62.5 kHz / CR 4/8)
- Adverts go out automatically; received adverts populate Recent Heard and (subject to your auto-add policy) the contact list
- Self-healing public-channel migration — earlier dev builds derived the Public channel secret from a hash, which didn't match the rest of the network. v0.1 detects this on every boot and repairs it automatically, without disturbing your custom channels
📱 UI
A horizontal seven-tile home layout. Swipe left/right to switch tiles.
| Tile | What it shows |
|---|---|
| 0 Home | Node name, freq/SF/RSSI/RX counters, six-button nav grid |
| 1 Recent Heard | Live list of nodes whose adverts you've received |
| 2 Radio Details | Current freq / BW / SF / CR / TX / sync word |
| 3 Advert | Long-press to send a manual advert |
| 4 GPS | Fix status, satellites, position, altitude, sentence rate |
| 5 Battery | Voltage, charge%, current, chip temp, remaining mAh |
| 6 Shutdown | Long-press to power down |
👥 Contacts
- Filter chip bar at the top: All / Chat / Rptr / Room / Sens / Fav. Swipe left/right to cycle, or tap a chip directly
- Per-row colour-coded type pill (C / R / RS / S) and 4-byte pubkey prefix for disambiguation
- Long-press a contact to toggle favourite (a star appears, the contact rises to the top)
- Tap a contact to open the detail screen, with a red Hold button that long-press-deletes (single tap is unbound to prevent accidents)
- Auto-add policies in Settings → Contacts: Auto All / Custom (per-type toggles) / Manual Only, with overwrite-oldest-when-full option
- Up to 2,000 contacts (PSRAM)
⚙️ Settings
- Node name (virtual keyboard input)
- Radio preset picker, TX power cycle, path hash mode (1/2/3 byte), UTC offset, home colour
- Brightness — eight-step ladder (13% → 100%), applies live as you tap
- Auto Off — Never / 1 / 2 / 5 / 10 / 30 minutes. Screen fades to black when idle; any touch wakes it back to your chosen brightness
- Manual Backup to SD trigger — force-write every NVS blob to the card
💾 Persistence
- NVS-primary, SD-mirror. Every save (prefs, channels, contacts, identity) writes to NVS first for speed, then to
/sdcard/meshcore/as backup. - If NVS is empty (fresh flash, factory erase) the device transparently restores from the SD backup on first boot.
- Channel message history written per-channel to
/sdcard/meshcore/messages/so the last several hundred messages per
channel survive reboots.
🛰️ GPS
- L76K module driven via UART1. Live fix status, satellites, position, altitude, NMEA sentence rate
- Long-press the GPS tile to toggle the module on/off. Off puts the L76K into standby (saves ~25 mA at the module while preserving the almanac for fast re-acquisition). The choice persists across reboots
- First cold-start fix typically 12–13 minutes outdoors; subsequent fixes after standby are much faster
🔋 Battery
- BQ27220 fuel gauge with the actual cell capacity (2000 mAh) configured at boot. LilyGo's example firmware ships with
set_design_capacity(1000), which scales every reading by 0.5x — Meck-P4 corrects this so current and SOC numbers reflect reality - Voltage-curve cross-check shown alongside the chip's reported SOC, with a note in the UI if they disagree by more than 15 points
- Note: the temperature shown is chip temp (BQ27220 die), not cell temp. The cell's NTC is wired to the LGS4056H charge IC for over-temp protection, not to the gauge
🕒 Clock sync
- Auto-syncs from incoming MeshCore advert timestamps (works on any healthy mesh, no extra hardware needed)
- Auto-syncs from GPS RMC sentences once the L76K acquires a fix
- Plausibility window rejects timestamps before 2025-01-01 or after 2032-01-01 so broken peers can't poison the clock
What's Not Yet Implemented
The big features people will likely want next, none of which are in v0.1:
- Direct messaging — DM compose, DM inbox with unread indicators, DM persistence to SD
- Roomserver access — login flow, message handling, mark-read on login
- Repeater admin — login, clock sync push, send advert, get status, neighbours, version
- Trace route — view the relay path of a received packet
- Notes app
- Audio player — local playback from SD
- Web browser & IRC client
- ESP32-C6 BLE companion firmware — the device is not yet usable as a Bluetooth companion to the iOS / Android MeshCore apps. The C6 chip is on the board but Meck-P4 doesn't drive it yet
- PCF8563 hardware RTC integration — the chip is initialised but not yet read on boot or written on shutdown, so the clock starts unset on every reboot until it syncs from an advert or GPS
- Deep sleep with wake-on-touch — the auto-off timer dims the screen, but the SoC doesn't enter deep sleep yet. Battery life is correspondingly short
- AMOLED variant untested
- Map tile rendering
- OTA firmware updates over WiFi via the C6
- Region scope (MeshCore v1.15+ compatibility)
If you want to chip away at any of these, PRs welcome. See the full roadmap in the README.
Known Quirks
- First boot after flashing: the device boots straight into Meck. If you've never used the board before, the contacts list will be empty until adverts start coming in.
- Battery life is short: no deep sleep is wired up yet. Expect a few hours of active use rather than days.
- Boot fade: the LilyGo factory boot fade-up to 100% brightness still runs before Meck applies your saved brightness. There's a brief flash to full white at startup. Startup currently takes around 11 seconds.
- Time displays as "not set" until the first advert or GPS fix syncs the clock.
Reporting Issues
The Meck-P4 channel on the MeshCore Discord
is the fastest path. GitHub Issues on the Meck-P4 repo also work for anything reproducible. Include the serial log if you can — idf.py monitor or any serial terminal at 115200 baud will show what's happening.
License
MIT for Meck-specific code. The combined firmware binary links libraries with mixed licensing including GPL-3.0 and is effectively GPL-3.0 when distributed.