2763 Commits
Author SHA1 Message Date
pelgraine 9606b42027 update readmes in EN and FR v1.15.1-max v1.15.1-Pro 2026-10-18 13:43:40 +11:00
pelgraine 04bbd582bd Pro combined ble wifi 4G and Audio builds 2026-10-18 13:30:51 +11:00
pelgraine 7f46dffb13 update to 1.15.1 and build date 2026-10-18 13:19:31 +11:00
pelgraine f7f5a3e10b Companion repeat mode (upstream v9) and path hash mode in device info
- Device info reply now ends with byte 80 (repeat on/off) and byte 81 (path hash mode), as upstream v9/v10, so the app can show Meck's path hash size.
     - Companion repeat mode, switched on only from the app: forwards packets while on. The app's radio command refuses repeat except on 433.000, 869.495 or 918.000 MHz; command 60 returns those frequencies. Stored at prefs byte 62 (spare, so existing devices start with it off).
     - While repeat is on, Settings, the serial CLI and import accept only those three frequencies. Settings shows a pop-up (English and French).
     - main.cpp: meckShowAlert now defined in every display build (was WiFi builds only), for the Settings pop-up.
     EOF

Updated firmware versions for the Max and firmware build date.
2026-10-14 07:03:29 +11:00
pelgraine 666e4a575f Updated image and added 🇬🇧 emoji to FR readme v1.15-max 2026-10-10 12:59:23 +11:00
pelgraine f9a698d6be Replace old image with new image in README 2026-10-10 12:58:16 +11:00
pelgraine 0f7b94e94c added 🇫🇷 emoji to make french readme link stand out better 2026-10-10 12:54:53 +11:00
pelgraine c1bae1a027 README: French translation (README_FR.md), font accuracy fixes, language links
New README_FR.md:
- French translation of the full README, AI translated
- Note at the top in French and English: the developer does not speak French, the French version is entirely AI translated, and suggested translations can be posted in the Meck channel on the MeshCore Discord or on the repo's Issues page
- Link back to the English README
- On-screen labels shown as the device's French text with the English in brackets; labels the device only shows in English stay in English
- French headings, with all in-page links pointing to the French anchors

README.md:
- Link to the French version at the top
- Accents: Noto Sans shows accents at every size; Montserrat shows them in Tiny-size text and titles, but not in 9pt text (Larger size, and some text that is always 9pt such as the WiFi home page status lines)
- Settings table: the font rows are now named Font Size and Font, as on the device
2026-10-10 12:50:32 +11:00
pelgraine e68a80cde7 Docs: French guide, 26 new v1.15 entries, accuracy fixes 2026-10-10 12:40:54 +11:00
pelgraine 4fabd99136 README: v1.15 additions, accuracy fixes, Max wording
v1.15 additions:
- New sections: Timezones (World Clock), Experimental Features (Language, Change Backlight to Alt+B on the Max, RX Boosted Gain, AGC Reset Int, Delete all contacts)
- Combined BLE & WiFi build: Max only in v1.15, T-Deck Pro combined build in a future release; added to the Max build table and contents
- WiFi: reason line on Could not connect; WiFi on/off from the WiFi home page; Connecting to Saved Wifi popup
- Export and import popups; Delete all contacts pointer in Contacts
- Settings channel rows switch between start and end when too long
- DMs and channel messages use the companion app's chosen region first
- Channel data for companion apps; +15 dBm Bluetooth on meck_max_ble and meck_max_ble_wifi
- Accents: Noto Sans at both sizes and Montserrat at Tiny now show them
- Road-map: v1.15 items; T-Deck Pro combined build as a to-do

Accuracy fixes:
- Max included where text said Pro only: OTA update, path hash S key, MeshCore Flasher, RTC, repeater admin keyboard, MeshCore Clients
- P and Mic keys: Pro Audio & Max
- Voice notes: Max records, receives and plays
- WiFi builds turn WiFi on at boot and join the saved network; only the combined build starts with WiFi off. WiFi build list now includes meck_audio_wifi_hyn and meck_max_wifi
- MeshCore Clients note: Bluetooth off at boot on all builds; WiFi and combined build behaviour
- TX Power range 1-22 dBm
- Two LilyGo devices, not three
- OTA Tools do nothing on the 40 MHz builds
- Build tables: added the three Pro HYN builds and the three 40 MHz builds; new Touch chips and HYN builds and 40 MHz battery-saver builds sections
- Max touch text expanded (CST328 on the Max; CST3530 on later Pro v1.1 units)
- New Canned Messages (T-Deck Max) section; speech bubble row updated
- Frontlight: Alt+B toggle documented
- Settings table: LoRa Antenna, Canned Messages, WiFi, WiFi Radio and 4G Modem rows
- Guide links now match the real file names

Removed: Meck Watch paragraph
2026-10-10 12:16:21 +11:00
pelgraine 1a90313bd3 Combined build: switching between Bluetooth and WiFi restarts the device; README section
Release note
Combined Bluetooth + WiFi build (meck_max_ble_wifi): switching between Bluetooth and WiFi now restarts the device each time, because Bluetooth only frees its memory on a restart and WiFi cannot start without it. Whichever you turn on first after a restart works straight away; turning on the other one shows a restart hint, asks you to press Enter again, restarts, and turns the chosen connection on by itself. From the companion app, set wifi.enabled now takes effect at the app's reboot.

Why
Bluetooth off keeps the Bluetooth stack's memory until a restart; WiFi off frees WiFi's driver. On device, WiFi on/off, Bluetooth on/off, then WiFi on failed ("failed to create task", largest free block 7668 bytes) and the app could not connect over Bluetooth until a restart.

Changes (combined build only, except README)
- main.cpp: tracks which connection has been on since this restart; a switch then needs a restart (also Bluetooth after the Web Reader freed it).
- main.cpp: "Switch to WiFi?" / "Switch to Bluetooth?" popup with "Enter again to restart"; a second press within 5 s shows "Restarting..." and restarts, saving pending contacts first (new MyMesh::saveContactsIfDirty(), as CMD_REBOOT does).
- main.cpp: the choice survives the restart in RTC memory and the connection turns on once the home screen shows. Normal restart or power-on: both off.
- main.cpp: app "set wifi.enabled" keeps the choice for the app's reboot instead of switching after 1 s. Reply text unchanged.
- UITask.cpp: restart hints ("restart into Bluetooth:" / "Press Enter to Restart into Wifi") only when a restart is needed; Enter or long press uses the confirmation.
- SettingsScreen.h: WiFi Radio and WiFi setup rows use the same confirmation.
- French added for all new text.
- README.md: new "Combined Bluetooth + WiFi build (T-Deck Max)" section.

Testing: PC harness on the real new logic: both directions, late and timely confirm, start-up pickup after the splash, app wifi.enabled 1/0, Web Reader case, normal restart and power-on leftovers. Full firmware build not run.
2026-10-10 11:37:36 +11:00
pelgraine a750c86c2a Import popup; Experimental Features: RX Boosted Gain and AGC Reset Int; pause charger serial readout
Import (main.cpp)
- Enter on "Import from SD" now shows "Importing... / Please Wait..." at once (French added). The import runs from loop() 1.5 s later (meckImportPoll), so the popup is on the e-ink while the import blocks; the existing result popups follow. Same pattern as the export popup (05949f21).
- An import that contains an identity still restarts the device itself 2 s after finishing (MeckImport.h), so the popup stays until the restart.

RX Boosted Gain (Settings > Experimental Features)
- New saved setting rx_boosted_gain (NodePrefs.h), default ON for new devices (MyMesh constructor) and for older prefs files.
- New row "RX Boosted Gain: ON/OFF" toggles and saves it (French added).
- The main loop's 500 ms re-assert (main.cpp) now applies the chosen mode: radio_reset_agc() (boosted) when ON, radio.setRxBoostedGainMode(false) when OFF. Previously boosted gain was always forced on, so OFF could not stick.

AGC Reset Int (Settings > Experimental Features)
- New saved setting agc_reset_interval, stored as seconds / 4 in one byte as upstream's companion does. Default 0 (off).
- New row "AGC Reset Int: Off" / "AGC Reset Int: 60 s" (French added). Enter opens text entry, as for channel regions; Shift+Backspace cancels. The value rounds down to a multiple of 4, empty or 0 means off, and it is capped at 1020 s (upstream wraps round above that).
- MyMesh::getAGCResetInterval() now returns it in milliseconds, as upstream, so the Dispatcher's periodic resetAGC() runs at that interval. Previously it was always off (base default 0).
- Label "AGC Reset Int" matches the Repeater admin screen; "AGC Reset Interval" did not fit at Larger in Montserrat.

Saved settings (DataStore.cpp)
- The two settings are appended at bytes 1524 and 1525 (checked against the real savePrefs write sequence); the prefs file grows from 1524 to 1526 bytes. Older files short-read the new fields and keep the defaults.

Charger readout (UITask.cpp)
- The temporary 10 s chargerDebugPrint() serial call is commented out while debugging BLE/WiFi. The readout code stays for the charger investigation.

Testing
- PC harness on the real new code: import popup timing and all three results in English and French; both rows' display, toggling and typed values (60, 30 -> 28, 1020, 5000 -> 1020, empty, junk) with the resulting Dispatcher interval; prefs byte offsets computed from savePrefs.
- Full firmware build not run in the test environment.
2026-10-10 11:24:04 +11:00
pelgraine 05949f21ed Export to SD: Compiling... Please Wait... popup before the export runs 2026-10-10 11:12:28 +11:00
pelgraine e9ec6e4648 Channel data (PAYLOAD_TYPE_GRP_DATA) send and receive for the companion app (issue #19)
Ports upstream MeshCore's channel datagram support (dz0ny, 9b842786, 5 Mar 2026, with follow-ups a21b83b1, ed326255 and 1d61df72). Upstream added it at protocol version 10, so apps may already send it to Meck, which reports 11.

Before: Meck decrypted incoming channel datagrams and silently dropped them, and the app's send command (62) was answered "unsupported".

Changes:
- BaseChatMesh::onGroupDataRecv() handles PAYLOAD_TYPE_GRP_DATA (2-byte little-endian data type, 1-byte length, payload), drops short or malformed packets, and passes the data to a new onChannelDataRecv() hook. Group text now checks the packet length before reading the text type byte.
- New BaseChatMesh::sendGroupData(): flood (using the channel's region scope) when no path is given, otherwise direct. Maximum payload MAX_GROUP_DATA_LENGTH (165 bytes).
- Companion: received datagrams go to the app as RESP_CODE_CHANNEL_DATA_RECV (27) and count as channel messages in the offline queue. CMD_SEND_CHANNEL_DATA (62) is handled with upstream's error codes.
- DATA_TYPE_RESERVED (0x0000) and DATA_TYPE_DEV (0xFFFF) defined.
Channel data is passed to the app only, not shown on the device. Upstream's MyMesh listener hook is not ported (Meck has no listener interface).

Tested on a PC against Meck's real Mesh and BaseChatMesh code with real encryption (AddressSanitizer on): flood and direct datagrams arrive intact; 165 bytes accepted, 166 refused; a malformed length is dropped; another channel's data is ignored; channel text is unaffected. The app frame and command 62 (flood, direct, 2-byte path hashes, every error case) were tested separately.

Issue #20 (rolling-window duty cycle) was already done in 444631e0 (30 Jun 2026) and shipped in v1.12.4: Dispatcher uses upstream's token bucket (upstream PR #1297) over a one-hour window instead of the old per-transmission silent period. Re-checked against upstream's current Dispatcher: same logic, and companion builds take the airtime factor from saved settings (default 1.0), as upstream does.
2026-10-10 11:04:26 +11:00
pelgraine c0f0275368 WiFi home page: Enter toggles WiFi radio; WiFi setup popups 2026-10-10 10:46:11 +11:00
pelgraine 4316e2d56d WiFi setup: Connecting, IP and Could not connect popups, 15 s limit; README WiFi steps 2026-10-10 10:42:06 +11:00
pelgraine 10776e89fa ui fix: text crowding in settings > channels view when regions added changed to ticker scroll method for longer channel names and regions to display properly 2026-10-10 10:02:18 +11:00
pelgraine 0b3c67e945 "Channels header: unread count margin matches footer" 2026-10-10 09:54:46 +11:00
pelgraine 7ea461e443 MeshCore v1.18 batch 3: path length checks, trace offset, GPS clock wrap, UTF-8 advert names, BLE receive queue, search results 24, trace timeout 2026-10-08 20:28:58 +11:00
pelgraine 46f46035ba MeshCore v1.18 batch 2: packet pool leak and millis wrap fixes, S3 pool checks, DM scope follows app, requests to non-contacts (P1), unmatched replies to app (P5) 2026-10-08 19:41:14 +11:00
pelgraine 894feb5858 MeshCore v1.18 batch 1: decrypt block check, skip empty channel slots, repeater serial buffer, un-scoped flood (v12), text type 3 relay and repeater 2026-10-08 19:19:26 +11:00
pelgraine 2dc28d7cd8 added last updated date to translation guide 2026-10-07 21:16:57 +11:00
pelgraine a4d34c8de5 Docs: French language guide and translation table (draft, v1.15) 2026-10-07 21:13:54 +11:00
pelgraine ccf67fbeb8 French UI batch 4: Repeater admin, Web Reader (incl. IRC, HTTP errors), Phone & SMS; compose header 2026-10-07 21:06:43 +11:00
pelgraine fc5bb119ce French UI batch 3: Notes, Reader, Audiobooks, Voice messages, Alarm, Map, Games (menu, Snake, Minesweeper, Game Boy) 2026-10-07 20:50:31 +11:00
pelgraine 597f3f50a0 French UI batch 2: Messages, channel picker, Contacts, Last Heard, Discovery, Trace, Path editor, Rx Log, main.cpp alerts 2026-10-07 20:39:10 +11:00
pelgraine 8a7aa1e28e French UI batch 1: Settings (all sub-screens, pop-ups, footers), home alerts and sub-states 2026-10-07 20:18:49 +11:00
pelgraine 4e47eb48be French UI stage 1 (Experimental > Language, home screen) + accented 7pt Noto/Montserrat and 12pt Noto Bold fonts
Settings > Experimental Features
- SettingsScreen.h: "Experimental Features >>" moved from the end of the
  top-level list to directly under "Rx Log >>".
- New Language row (all T-Deck builds), first in the Experimental
  sub-screen. It shows the action: "Language: Change to French" in
  English, "Langue : Passer a l'anglais" (with the accent) in French.
  Enter toggles and saves.
- Choosing French swaps the Classic font style to Noto Sans (Classic has
  no accents); the text size is left alone. While French is on, the Font
  picker skips Classic. Switching back to English leaves the font as is.
- NodePrefs.h, DataStore.cpp: new pref ui_lang at byte 1523
  (0 = English, 1 = French). The prefs file grows to 1524 bytes; older
  files load as English.

Translation framework
- MeckLang.h (new): MECK_TR("English", "French") picks the string for
  the current language; meckUiLang() in main.cpp reads ui_lang. French
  strings are UTF-8, written as \x escapes so source files stay ASCII.

French translations (UITask.cpp)
- Home tiles, Phone tile and the status strip.
- First view of each home page: Recent heard, Radio, Bluetooth, WiFi,
  Advert, GPS, Battery gauge, Hibernate/power off options, Timezones.
- Start-up key hint box.
- Not yet translated: Settings and every other screen, and the home
  pages' sub-states (GPS UTC editor, power-off confirmation, Timezones
  editor hints).

Fonts
- New Adafruit GFX fonts covering U+0020-U+017F (ASCII, Latin-1
  Supplement, Latin Extended-A: French, Czech and other European
  accents), generated with stock fontconvert from the same sources as the
  fonts they replace. Their ASCII glyphs are byte-identical, so English
  text is unchanged:
  - fonts/NotoSans7pt8b.h (Noto Sans Tiny), from Google Fonts'
    NotoSans[wdth,wght].ttf
  - fonts/Montserrat7pt8b.h (Montserrat Tiny), from Google Fonts' static
    Montserrat Regular (npm @expo-google-fonts/montserrat 0.4.2)
  - fonts/NotoSansBold12pt8b.h (Noto titles and clock face), from Google
    Fonts' static Noto Sans Bold (npm @expo-google-fonts/noto-sans 0.4.2)
- MeckFonts.h: Noto size 0 -> NotoSans_Regular7pt8b, Noto sizes 3 and 5
  -> NotoSans_Bold12pt8b, Montserrat size 0 -> Montserrat_Regular7pt8b.
- Removed the replaced fonts: NotoSans7pt7b.h, Montserrat7pt7b.h,
  NotoSansBold12pt7b.h.
- Effect for all users: accented letters in names and messages now show
  at Tiny size with Noto Sans and Montserrat, instead of being reduced to
  plain letters. Classic is unchanged.
- Still without accents: Montserrat at Larger (Montserrat9pt7b).

Display driver
- GxEPDDisplay.cpp: measureTextRawStyled() and drawTextRawStyled() (home
  tiles and status strip) now decode UTF-8 when the font has accented
  glyphs: ASCII through Adafruit GFX as before, other characters from the
  font's glyph table, as print() does. Plain ASCII labels take the old
  path unchanged.

Tested on device (7 Oct 2026): Classic + Tiny -> Change to French swaps
to Noto Sans automatically; the home tiles and translated home pages
display correctly in Noto Sans Tiny. Not yet tested: French at Larger,
French with Montserrat, accented 12pt bold titles (accented capitals are
6 px taller than English ones), English screens for regressions.
2026-10-07 19:07:02 +11:00
pelgraine 2ca97fa8ce v1.15: Settings > Experimental Features (delete all contacts, Alt+B-only backlight); TEMP Max charger readout
Version
- MyMesh.h: FIRMWARE_VERSION default "Meck v1.14" -> "Meck v1.15";
  FIRMWARE_BUILD_DATE updated.
- variants/lilygo_tdeck_pro/platformio.ini,
  variants/lilygo_tdeck_max/platformio.ini: FIRMWARE_VERSION strings
  v1.14 -> v1.15.

Settings > Experimental Features
- SettingsScreen.h: new "Experimental Features >>" folder row as the last
  top-level Settings row, opening "Settings > Experimental".
- Delete all contacts (all T-Deck builds), ported from Meck-P4 v0.7.4.
  Flow: "Delete all contacts?" box (Enter:Yes Q:No) -> second "Are you
  sure? This cannot be undone." popup (its Enter is ignored for the
  first second) -> "Purging" -> "Contacts deleted" or "Purge failed" ->
  restart 3 s later. Removes every contact, with favourites and custom
  paths, and the DM history; channel messages are kept. Q cancels at
  either confirmation; keys are ignored once the purge starts.
- MyMesh.h: purgeAllContacts() closes any chunked contact save still in
  progress, empties the contact table and saves the empty set.
- ChannelScreen.h: purgeDMs() marks the DM entries in
  /meshcore/messages.bin empty in place and re-saves, keeping channel
  messages, and clears the DM unread count.
- main.cpp: meckPurgeAllContacts() runs both and checks the contacts file
  is empty afterwards. All touch is ignored while the purge box is open.
- Change Backlight to Alt+B (Max only): ON stops the heart touch key
  toggling the frontlight, and Alt+B then lights it at the Backlight
  Brightness setting. OFF leaves both as before.
- NodePrefs.h, DataStore.cpp: new pref backlight_alt_b_only at byte 1522
  (prefs file now 1523 bytes); older files load it as 0 (heart key on).
  Timezones comment "these final fields" -> "these fields".

TEMPORARY (Max only; remove after the charging investigation)
- TDeckProMaxBoard.h, TDeckProMaxBoard.cpp: chargerDebugPrint(), a
  read-only SY6970 status, fault and register dump plus a BQ27220 gauge
  line on serial.
- UITask.cpp: calls it every 10 s from UITask::loop().
2026-10-07 06:33:58 +11:00
pelgraine 3fc6e73014 Max: combined ble wifi initial build test 2026-10-05 21:27:53 +11:00
pelgraine 355cd594e6 BLE: MECK_BLE_TX_POWER build flag (default +9 dBm), meck_max_ble at +15 dBm 2026-10-01 07:02:00 +10:00
pelgraine 8154096259 UI: fix highlight bar position with Noto/Montserrat and Large text 2026-09-30 21:22:32 +10:00
pelgraine 3cc6d2c2c0 Max: Timezones world clock page 2026-09-30 21:22:08 +10:00
pelgraine fe8bffd737 Discovery: list scan replies only (remove passive advert feed bug) 2026-09-29 20:22:38 +10:00
pelgraine 7ca48331f4 get rid of annoying extensions json prompt 2026-09-29 19:03:23 +10:00
pelgraine 178b2ef3cf Remove T5S3, T-Echo, CardKB and nRF support 2026-09-29 06:46:19 +10:00
pelgraine 1328eec434 add build flag to max fastlut build for max refresh rate 2026-09-21 06:09:13 +10:00
pelgraine bf7aff7f9a Add meck_audio_ble_fastlut test env (register waveform, 9 frames) 2026-09-21 06:08:04 +10:00
pelgraine 7fdf87b6b6 fix broken links in readme v1.14 2026-09-15 19:35:54 +10:00
pelgraine cd8c23838b fix broken links in readme 2026-09-15 19:35:16 +10:00
pelgraine b6b9fe68cf Merge branch 'dev' 2026-09-15 19:30:53 +10:00
pelgraine db87d5394c fix readme max battery digit 2026-09-15 19:29:46 +10:00
pelgraine 64621927dd Merge branch 'dev' 2026-09-15 19:23:22 +10:00
pelgraine 1bb2a9bf85 Readme updated to align with main branch additions 2026-09-15 19:19:50 +10:00
pelgraine ed8869e135 Bringing over Commit 0bbbc04 changes from main into dev 2026-09-15 19:19:04 +10:00
pelgraine d52802fed3 Update readme. Update build date. Fix stale comments in Max ini. 2026-09-15 19:09:17 +10:00
pelgraine e1964d00cb GBCEmulatorScreen.cpp → examples/companion_radio/ui-new/, fingerprint 1093 (build 28 was 1071). Replaces build 28; nothing else changes.
What changed
Quiet period 2 s → 20 s. A background save now only happens after the cart RAM has been untouched for 20 seconds, so ordinary in-game writes during active play no longer trip it. A real menu save is followed by a pause, so it still gets written.
Checksum guard. Before any save, background or on-quit, the live cart RAM is checksummed against what was last written; if the bytes are identical, nothing is written to the card. The game replaying identical state, which is what caused the save-just-after-opening, no longer touches the SD card at all. Seeded from the loaded .sav at launch, so opening a game and idling never writes.
2026-09-15 18:58:39 +10:00
pelgraine 37b3d343e7 GBC emulator: gate out of the 40 MHz battery-saver builds
The emulator needs 240 MHz to run at speed, so it has no place on the
40 MHz builds (meck_max_standalone_40mhz and the Pro's 40 MHz env).

- GamesMenuScreen.h: the Game Boy entry is omitted from the games menu
  on MECK_40MHZ_TEST builds (NUM_GAMES drops to 2, in lockstep with the
  entry list). Snake and Minesweeper are unaffected -- they run fine at
  40 MHz. The menu simply shows two games instead of three.
- UITask::gotoGBCScreen(): refuses on MECK_40MHZ_TEST with a brief
  "Game Boy needs 240MHz" alert and stays put. This is the single point
  every launch route (tile, J-key, games menu) funnels through, so it
  backstops the menu omission -- nothing can reach the emulator on
  those builds.

Files: examples/companion_radio/ui-new/{GamesMenuScreen.h, UITask.cpp}
2026-09-15 18:51:01 +10:00
pelgraine 5a911619f7 GBC sound (T-Deck Max), mesh stays live in-game, fast waveform at 12 frames, wrap fix
SOUND (Max, ES8311; Pro stays silent)
- minigb_apu vendored from Meck-P4 (MIT), run at 22050 Hz: at 44100 it
  cost 3.6-4.0 ms of the 16.7 ms frame and the game fell to 0.98x, which
  drained the DMA queue and glitched. Per-frame timings (core / apu /
  i2s wait) now print with the speed line.
- Bring-up reuses the notification-tone path: shared Audio object owns
  I2S port 0 (with MCLK), XL9555 routing and amp, then codec init after
  the clocks are running. Raw PCM written per frame; a repeated sample
  every sixth frame keeps production a hair above the DAC so its clock
  paces the game instead of the queue running dry.
- Software gain 1/8 (codec DAC sits at 0 dB); GBC_AUDIO_SHIFT to tune.
- 950 ms delay line (PSRAM) so sound lands with the picture, which
  reaches the glass ~1 s after its frame; GBC_AUDIO_DELAY_MS to tune.
- Games start muted; mic key toggles the codec mute in both keyboard
  drivers' raw mode; footer shows the current hint. Amp off on quit.
- Notification tones skipped while a game runs (game owns the codec).

MESH LIVE DURING PLAY
- The OTA-style radio pause is gone (GBC_PAUSE_RADIO=1 restores it):
  the mesh runs on the other core and already tolerates the panel
  blocking the loop. Game header now matches the home screen's -- the
  cumulative unread channel count where the node name goes, clock,
  battery percent. "New:" toasts suppressed only while a ROM is running
  (Snake and Minesweeper keep them).

DISPLAY
- Fast register waveform set to 12 frames per push (FAST_LUT_FRAMES):
  judged the best balance of UI speed and contrast. Interface only; the
  game keeps the factory waveform.
- Windowed game refresh dropped: measured to save nothing, and it left
  the footer row unrefreshed. Normal partial refresh, change-detected.
- Adafruit GFX auto-wrap turned off in the e-ink driver (all e-ink
  builds): it dropped a glyph onto the next line's margin when a line
  ran a few pixels past the edge (seen with Larger Noto in compose).
  Compose wrap width also allows for the driver's 2-unit x offset.
- Game start does one full refresh (tried as a ghosting fix; NPC
  ghosting in Pokemon Gold is the game + dither + factory partial
  waveform and shows on the stock build too).

Files: examples/companion_radio/{main.cpp, ui-new/GBCEmulatorScreen.{h,cpp},
ui-new/UITask.cpp, ui-new/minigb_apu.{c,h}}, src/helpers/ui/GxEPDDisplay.cpp,
src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.cpp,
variants/lilygo_tdeck_{max,pro}/TCA8418Keyboard.h
2026-09-15 18:42:55 +10:00
pelgraine 1bad37d1ad Large font channel message view word wrap bug fix: What changed:
Driver: setTextWrap(false) once at init. GFX no longer moves text to the next line by itself, anywhere. This is what put the stray "t" on the margin; without it, a line the screen miscounts is clipped at the edge instead, which is the lesser evil for a UI that does all its own wrapping. Applies to every e-ink build, Pro and Max.
Compose: the usable line width is now the panel width less the driver's 2-unit x offset, so the compose wrap and the glyphs' real positions agree and lines wrap one word earlier when they need to.

GxEPD2_310_GDEQ031T10_FAST.cpp → fingerprint 473 (was 464). The 9-frame bytes (0x89 / 0x49 / 0x09) become 0x8C / 0x4C / 0x0C: same level bits, count 12. Improves colour density in Max fastlut test build.
2026-09-13 21:10:08 +10:00