Commit Graph

1018 Commits

Author SHA1 Message Date
pelgraine ed039aa711 SMS: show unread count on the inbox badge instead of conversation count.
The "SMS Inbox" badge on the Phone & SMS landing screen previously showed
the number of conversations regardless of read state. It now shows the
number of unread received messages and disappears when there are none.
Read state is tracked persistently, so it survives reboots and modem
power-cycles (the flag lives in each record on the SD card).

SMSStore:
- Add a `read` byte to SMSRecord, reusing one of the reserved bytes so the
  record stays 256 bytes and every existing field offset is unchanged
  (existing .sms files remain readable).
- saveMessage marks sent messages read and received messages unread.
- loadConversations scans each file and reports unreadCount (received
  messages with read=0); preview / last-message behaviour is unchanged.
- markConversationRead / markFileRead flip received-unread records to read
  in place (open "r+", rewrite only the affected records).
- begin() runs a one-time migration on first boot that marks all
  pre-existing history read, gated by a marker file (/sms/rdmig.dat), so
  old messages do not all appear as unread after the update.

SMSScreen:
- Landing-screen badge sums unreadCount across conversations, hidden at zero.
- Opening a conversation marks it read and clears its in-RAM count.
- A message arriving while its conversation is open is marked read.
- Inbox reloads on the landing screen as well as the inbox view, so the
  badge updates live when a message arrives.
2026-06-07 06:15:45 +10:00
pelgraine 57b63bed47 Max - grid alignment fixes and more cells 2026-06-07 05:52:30 +10:00
pelgraine 38656f9d1d Add on-device Rx Log packet sniffer and RX packet counter
RX packet counter: shows total received packets (flood + direct) on the
radio details page; RAM-only, resets on boot and on any SF/freq/BW change.

Rx Log: app-style packet sniffer opened from Settings > "Rx Log >>".
Captures the last 100 received packets pre-filter via Dispatcher::logRx
into a PSRAM ring, with decoded "sender: message" lines matched by packet
hash for decryptable channels. Each entry shows route/type, time, size,
hash, path, channel or From/To, SNR. W/S scroll, Q back to Settings;
T5S3 swipe-scroll rides the same path.

Files: MyMesh.h/.cpp, RxLogScreen.h (new), UITask.h/.cpp,
SettingsScreen.h, main.cpp.
2026-06-07 05:14:16 +10:00
pelgraine 353048aab3 So the power investigation wraps up like this:
GPS — fixed (the "off" toggle and boot path now actually cut the XL9555 rail). Kept in main.cpp + UITask.cpp.
BLE controller — the ~13 mA between the BLE build (BLE off) and standalone is the controller staying initialised; the boot-gate in SerialBLEInterface.cpp/.h defers BLEDevice::init() until first enable, reclaiming it. That's the meaningful idle win.
CPU, gyro rail, ES8311, frontlight — all measured and ruled out. The residual ~12 mA Max-vs-Pro is distributed always-on hardware with no software switch — hardware overhead, not a bug.

Defer ESP32 BLE controller bring-up to first user enable
MyMesh::startInterface() called serial.enable() unconditionally at boot. On the ESP32 BLE build this ran the deferred-init SerialBLEInterface's _realBegin()/BLEDevice::init() and powered the BT controller before main.cpp's boot-time disable(), which only stops advertising and cannot power the controller back down -- so the controller stayed up while "off", drawing ~13 mA at idle. Guard the enable() so ESP32 BLE builds skip it at boot; the controller now comes up lazily on the first enable() when the user turns Bluetooth on from the Bluetooth page. WiFi builds are unaffected and still enable at boot.
2026-06-07 00:09:56 +10:00
pelgraine 8ac9aeed28 Max - fixed usb C wake auto power on after shutdown is used, and minor ui fix to home screen when BLE is on but not connected 2026-06-06 21:23:44 +10:00
pelgraine 378db7932c udpate firmware version 2026-06-06 21:09:48 +10:00
pelgraine ea98eaead4 audiobook player guide updated.
Summary of what changed in each file, all confined to the change points shown in the diffs:
ChannelScreen.h — ChannelMessage gains a session-only scope_idx (initialised to 0xFF in the constructor and explicitly reset to 0xFF on SD load, since region is not persisted); addMessage gains a trailing defaulted scope_idx and stores it. The message-list line now renders (Xh)(Xb) Xm, with the byte figure taken from path_len's upper bits for floods and from the_mesh.getNodePrefs()->path_hash_mode + 1 for the 0xFF/0 sentinels. The path overlay shows Route: ... (N-byte) and a new Region: line (name, or (reg unknown), or nothing when unscoped).
MyMesh.h / .cpp — a fixed 28-entry SCOPE_NAMES table, a _scope_keys array precomputed once at the end of begin() via initScopeKeys(), resolveScopeIndex() (matches pkt->transport_codes[0] against the candidates; 0xFF unscoped, 0xFE unmatched), and the public getScopeName() accessor. onChannelMessageRecv resolves the index and passes it to newMsg.
AbstractUITask.h / UITask.h / UITask.cpp — newMsg gains a trailing uint8_t scope_idx = 0xFF; only the channel addMessage call forwards it. DMs and sent echoes keep the default, so they stay unscoped.
MsgFileRecord and the SD save/load format are untouched, so there's no version bump.
2026-06-06 20:42:21 +10:00
pelgraine 28f50ae373 update firmware build date. add toaster popup to voice messages screen for when contact doesn't have direct path 2026-06-05 02:58:31 +10:00
pelgraine 585bf7e381 Fixed audiobookplayer crowded footer text and filtering out m4b files for now until we get that sorted. Fixed voice message recording playback for the max. 2026-06-05 02:39:29 +10:00
pelgraine 9080af8037 Max - increased buzzer length 2026-06-05 00:34:47 +10:00
pelgraine fb4d8273a9 Max - New buzzer(vibrate) option in custom channel notification preferences - silent buzz notification. 2026-06-04 23:54:07 +10:00
pelgraine b6e3c7e0a5 implemented $PCAS04,7 - Multi-constellation mode (GPS, Galileo, BeiDou, and QZSS)
The default LilyGo/MeshOS firmware uses GPS-only ($PCAS04,1) & $PMTK869,1,1 - EASY predicted ephemeris
2026-06-04 23:25:03 +10:00
pelgraine f6bce4f5ee Max - fix missing -D HAS_4G_MODEM=1 flags. Revised settingscreen so it uses a scroll bar instead of the heading total counter. New brightness scale in settings to control heart button brightness toggle strength, which also persists after reboot. 2026-06-04 22:29:14 +10:00
pelgraine 0a92f5ba48 Max - three touch capacitive buttons wired. Heart = backlight at full brightness. Speech bubble = opens channel picker. Paper plane = opens DM inbox 2026-06-04 21:44:15 +10:00
pelgraine 1613b81004 Max - touch support working!! 2026-06-04 21:24:14 +10:00
pelgraine 4db03adb3a Max - 4G working! 2026-06-04 20:37:53 +10:00
pelgraine 30d2e6aee7 max - fix offset home ui word wrap issue on 3 pages 2026-06-03 20:46:53 +10:00
pelgraine 82bd883723 remove pngdec from audiobookplayerscreen due to ble compilation bug 2026-06-03 20:06:29 +10:00
pelgraine 70e150e9c3 What changed and what to expect:
The fix (six sites: 948, 978, 1519, 1651, 1719, 1906): the indexer now chooses pixel-vs-char wrapping from _display->getFontStyle(), the same basis the renderer (1200), the layout sizing (1336), and the cache key already use. With all four agreeing, the indexer's recorded page boundary lands on the exact byte where the renderer's height-based stop lands — no more swallowed run between pages.
Version bump (INDEX_VERSION 13 → 14): your existing .idx caches were built by the old indexer and would otherwise be reloaded as-is (same font key), so the fix would appear to do nothing. Bumping the version makes the loader discard every v13 cache and rebuild it.

All six edits are in and braces balance (267/267). Here's what changed in Audiobookplayerscreen.h:

PNGdec include (47) and cover size 40→30 (67) — 30 virtual units ≈ 55px.
PNG draw callback coverDrawCallbackPNG (147) — nearest-neighbour downscales the 256px source line-by-line and dithers to 1-bit using the same Bayer matrix as the JPEG path. The decoder is heap-allocated per-decode (new PNG()), mirroring how the JPEG path uses new JPEGDEC(), so there's no permanent BSS cost.
decodeFolderCoverPNG() (419) + tryLoadFolderCover() (505) — reads cover.png from _currentPath into PSRAM and decodes it.
Hooks in both openBook (1099) and advanceTrack (1198), so the cover loads on open and persists as tracks auto-advance within an album. It only loads when there's no embedded cover, so M4B/ID3 embedded art still wins; music (no embedded art) gets the folder PNG.
Layout (1531, 1556) — cover now draws below the artist line, above the status/Paused-Vol line, exactly where you wanted it.
2026-06-03 19:24:19 +10:00
pelgraine 6487fcf4e6 same fix 2026-06-03 18:40:49 +10:00
pelgraine 0d2f27e615 Here's what each does:
target.h — declares meck_audio_route_amp() and meck_audio_codec_init() in the bridge (54-55), guarded by HAS_ES8311_AUDIO, ready for the alarm/voice paths to reuse later.
target.cpp — includes ES8311.h (6) and defines both helpers where board and the codec driver are visible: route+amp (100-102), and the once-only es8311_init_44100_16bit() (108-110).
Audiobookplayerscreen.h — forward-declares both (54-55); ensureI2SInit() now does route+amp and the 5-arg setPinout with MCLK on MAX (268-270); and meck_audio_codec_init() runs right after connecttoFS (1142). The Pro path is untouched.
2026-06-03 18:31:07 +10:00
pelgraine 8c6b3b1029 redid commit e0e011e and also added Vendor ESP32-audioI2S into lib/ with ES8311 APLL + set-once I2S edits 2026-06-03 17:59:38 +10:00
pelgraine 0a119eac4f initial audio playback working success - fixed pin 41 guard dac issue for pro variant by guarding with has es8311 audio 2026-06-03 15:10:28 +10:00
pelgraine d66f202081 decoupled the Max from the Pro variant; fixed e-ink offset in the max 2026-06-03 01:52:48 +10:00
pelgraine fc322070ae max - dropped keyboard bl brightness to 8, screen bl brightness to 1 for maximum dark room friendliness. Fix e-ink x offset 2026-06-03 00:16:18 +10:00
pelgraine 6966ae724b max - reduced keyboard backlight brightness to 32 2026-06-02 23:07:32 +10:00
pelgraine ef13cfac7e max - screen backlight dropped to 5, keyboard backlight brightness dropped by half to 128. Will need to revise message flash in settingscreen.h to use buzze instead of keyboard backlight led 2026-06-02 22:54:57 +10:00
pelgraine 6f95884d47 STUPID BACKLIGHT IS WORKING FINALLY AAAH 2026-06-02 22:15:15 +10:00
pelgraine 12dc40db33 max - keyboard backlight works - press both shift keys to turn on and off 2026-06-02 18:16:25 +10:00
pelgraine 590655016a initial max updates - not yet working 2026-06-02 18:03:09 +10:00
pelgraine 77689870ad T5S3 ui fixes, including bigger minesweeper grid square.
Contact list display bug fix for all devices: MyMesh.h — added onAdvertRecv override declaration (line 214), alongside the other contact-related overrides.
MyMesh.cpp — added the implementation (lines 374-387). It calls BaseChatMesh::onAdvertRecv() first to let all normal processing happen (auto-add, replay guard, path caching, etc.), then unconditionally looks up the contact by pubkey and bumps lastmod to local RTC time. This way, even when the base class's replay guard early-returns (because timestamp <= last_advert_timestamp), the contact still bubbles up in the recency-sorted contacts list since we're actively hearing it.
2026-05-23 07:08:46 +10:00
pelgraine 834cd5fc87 Updated channel sharing so channel is immediately added upon receipt of DM, no additional steps required 2026-05-23 06:51:06 +10:00
pelgraine 4cc15f7ab0 Delete t-echo card and t-echo lite folders as no longer working on those; support json import & export config; new method for creating private and hashtag channels 2026-05-23 04:04:45 +10:00
pelgraine 47a7f2f9d1 add 100 and :D emoji; update firmware version to 1.11;; config json import and export on device to SD now supported 2026-05-22 10:08:24 +10:00
pelgraine ef62b7145c TD Pro - add custom tones for 4G variant 2026-05-15 08:32:36 +10:00
pelgraine f6cc939c4d tdpro add minesweeper game 2026-05-15 07:29:14 +10:00
pelgraine 2907cc64f3 updated firmware build date; added [J] Games to home screen; added game sub screen; added basic Snake game 2026-05-15 06:59:49 +10:00
pelgraine 1e589b3eb9 td pro - custom notification sounds enabled for t-deck pro audio variant 2026-05-12 17:14:11 +10:00
pelgraine b0ad1c4901 selective channel notification functions - off/mute, only at tags, or alll, under channels in settingscreen 2026-05-12 05:25:43 +10:00
pelgraine ceb29ba662 tdpro - channel message history delete function - long press on screen to bring up menu 2026-05-12 04:50:32 +10:00
pelgraine 18b9ab6c4d update firmware version and build date 2026-05-12 04:24:30 +10:00
pelgraine 661157e368 Fix trace screen for t5s3 and add home icon for trace screen to t5s3 2026-05-07 20:27:58 +10:00
pelgraine 3596ad558d Fix missing data store persistence updates - font style, scope name and corresponding scope key - now sticks across reboots. Revised tdpro home ui offset to original settings. Fixed tpro hibernate icon positioning. 2026-05-07 17:57:19 +10:00
pelgraine 6de664ea37 Dm message persistence; fixed home ui offset alignment; trace route screen addition 2026-05-07 17:23:04 +10:00
pelgraine 708b96e0e8 T-Echo Card audio support initial stages - codec2 attempts 2026-05-07 05:47:18 +10:00
pelgraine 44353fcf9e hibernation page navigation bugfix 2026-05-03 23:15:32 +10:00
pelgraine 4ba130ccfa update readme for v1.8; added fix: robust SPIFFS recovery when auto-format fails
SPIFFS.begin(true) auto-formats on mount failure, but the auto-format
itself can fail if the partition contains residual data from a previous
firmware (e.g. stock LilyGo, Meshtastic, or MeshCore with a different
partition layout). When that happens the firmware previously printed
"SPIFFS format FAILED!" and continued in a broken state with no
persistence.

Now on auto-format failure:
1. Find the SPIFFS partition via esp_partition_find_first()
2. Erase it completely with esp_partition_erase_range()
3. Call SPIFFS.format() + SPIFFS.begin(false) with up to 3 retries

Added #include <esp_partition.h> under ESP32 guard.

The existing first-boot display feedback ("Formatting storage...
First boot - please wait") is unchanged -- it fires on the initial
mount failure. The new partition erase code only triggers if the
auto-format also fails.
2026-05-03 21:22:07 +10:00
pelgraine c2bfc3c985 Add true power-off via BQ25896 BATFET disconnect
Hibernate (deep sleep) leaves the BQ25896 charger IC powered, drawing
~30-60uA quiescent from BAT. This adds a second option on the shutdown
page -- "power off" -- that writes the BATFET_DIS bit in BQ25896 REG09
to fully disconnect the battery from VSYS. Leakage drops to ~12-23uA
(IC internal only). Wake requires USB-C plug-in.

Shutdown page now shows two options with a cursor (up/down to toggle):
  > hibernate: long press/Enter   (T-Deck Pro)
    power off: long press/Enter
  > hibernate: long press          (T5S3 / other)
    power off: long press

Selecting "hibernate" triggers immediately (unchanged behaviour).
Selecting "power off" shows a confirmation prompt:
  power off device?
  usb-c to wake
  Enter:yes  q:no

Power-off display suppresses the header (node name, clock, battery)
and shows only "powering off..." and "plug in USB-C to turn on".

The 's' key shortcut to settings is gated on the shutdown page so it
passes through to the hibernate/power-off selection toggle instead.
Both the TCA8418 handler (loop) and the broader handler
(handleKeyboardInput) are gated via isHomeOnShutdownPage().

PRESS_LABEL macro: removed dead UI_HAS_JOYSTICK branch (no Meck
device has a joystick), collapsed to a single #define "long press".
Joystick input polling block in loop() also removed (dead code behind
#if UI_HAS_JOYSTICK, never compiled for any Meck build).

BQ25896 I2C sequence follows TI recommendation (E2E forum, Jeff/TI):
  1. Read REG09
  2. Write BATFET_DLY=1 (bit 3) -- delays disconnect so I2C completes
  3. Write BATFET_DIS=1 | BATFET_DLY=1 (bits 5+3) -- last I2C write
The write happens after display turnOff but before board powerOff, so
I2C pull-ups on VDD3V3 are still alive. Board enters deep sleep, then
BATFET opens after tSM_DLY (~10-15s). Skipping the delay risks leaving
the BQ25896 I2C engine in an undefined state that can prevent wake on
USB-C plug-in (device soft-brick requiring battery disconnect).

REG09 bit map (confirmed from Linux kernel bq25890_charger.c):
  Bit 7: FORCE_ICO
  Bit 6: TMR2X_EN
  Bit 5: BATFET_DIS  (0x20) -- disconnect battery
  Bit 4: JEITA_VSET
  Bit 3: BATFET_DLY  (0x08) -- delay before disconnect
  Bit 2: BATFET_RST_EN (0x04) -- QON wake (not wired on T-Deck Pro)
  Bit 1: PUMPX_UP
  Bit 0: PUMPX_DN

Schematic confirms QON (pin 12) has R4 10K pull-up to REGN with no
user-accessible button -- USB-C is the only wake path from ship mode.

Guarded by #ifdef I2C_ADDR_BQ25896 so it compiles on all platforms
but only activates on boards with the charger (T-Deck Pro, T5S3).

Files changed:
  UITask.h   -- _full_poweroff, setFullPowerOff(), isHomeOnShutdownPage()
  UITask.cpp -- shutdown page UI, input handling, BATFET write,
                PRESS_LABEL cleanup, joystick removal
  main.cpp   -- 's' key gated on shutdown page (both handlers)
2026-05-03 20:24:20 +10:00
pelgraine a7b44de613 Went back to the previous method of markAllChannelsRead() for WIfi and BLE envs ie non-standalone devices so msgs marked read on device when app is connected 2026-05-03 18:40:28 +10:00
pelgraine 7ebafc39ee update firmware build date 2026-05-03 18:20:48 +10:00