Skip to content

Meck-P4 v0.1 — First Pre-Release for the LilyGo T-Display P4

Pre-release
Pre-release

Choose a tag to compare

@pelgraine pelgraine released this 09 May 08:14
· 106 commits to main since this release

The 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

⚠️ LilyGo T-Display P4 (TFT version)⚠️ The AMOLED variant has not been tested but should be close — adjust the display init in
main/examples/lvgl_9_ui/main.cpp if you want to try it.

Flashing

IMG_2838

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):

  1. Go to https://flasher.meshcore.io
  2. Scroll to the bottom and select Custom Firmware
  3. Select the meck-p4-0.1.bin file you downloaded
  4. Click OK for the warning about erase files because it's a merged binary.
  5. 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.