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.
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().
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.
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}
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
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.
EXPERIMENT (Max only, env meck_max_ble_fastlut; all other builds unchanged)
- New vendored driver src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.{h,cpp}:
the GxEPD2 GDEQ031T10 driver with a selectable partial-refresh
waveform. Default is "LUT from register" loaded with the register
tables bitbank2/bb_epaper uses for this panel on the T-Deck Pro (one
9-frame push per pixel); the factory OTP waveform stays available.
Full refreshes unchanged. Measured on the Max: partial refresh 244 ms
(652 ms on the factory waveform) on home, menus, ROM list and typing.
Cost: one short push per pixel gives weaker blacks and half-develops
dithered stipple, so it suits text and does not suit the game.
- GxEPDDisplay: setFastWaveform() and fastPartialsSinceFull(), no-ops
outside the experiment env. Switching back to the factory waveform
hibernates the panel so the next refresh goes through a hardware
reset (tested as a ghosting fix; it was not one, kept as a clean
hand-over).
- UITask::setCurrScreen: after EINK_FAST_FULL_EVERY (20) fast partials
the redraw at the next screen change is a full refresh, so the
register waveform's ink imbalance is cleared where a redraw is
happening anyway rather than mid-typing.
- GBC emulator switches the driver to the factory waveform while a
game runs (its dithered picture needs the longer drive) and back to
fast on quit.
- Finding, for the record: moving-sprite ghosting in Pokemon Gold
appears on the stock build too, so it is the game plus dither plus
the factory partial waveform, not the experiment.
GBC EMULATOR (all T-Deck builds)
- "Loading..." alert box the moment Enter is pressed on a ROM row; the
multi-second SD read now runs on the next loop pass, after the box is
on the panel, instead of inside the key handler.
- Games start with a full refresh (clean panel; added during the
ghosting investigation, kept pending review).
- Save writes are timed and the durations logged (remove/open/write/
close), after one unexplained ~45 s UI stall coincided with a save.
Files: examples/companion_radio/ui-new/GBCEmulatorScreen.{h,cpp},
examples/companion_radio/ui-new/UITask.cpp, src/helpers/ui/GxEPDDisplay.h,
src/helpers/ui/GxEPD2_310_GDEQ031T10_FAST.{h,cpp},
variants/lilygo_tdeck_max/platformio.ini
PRO PORT
- The emulator now builds for every T-Deck Pro companion env as well as
the Max (guard moved from LilyGo_TDeck_Pro_Max to LilyGo_TDeck_Pro in
main.cpp, UITask.{h,cpp}, GamesMenuScreen.h and the emulator files;
the T5S3 stays excluded). Pro keyboard driver gains the same raw
joypad mode as the Max's, minus the both-shifts backlight chord, which
stays Max-only along with toggleKeyboardBacklight().
- Same chip, panel, keyboard controller and SD layout as the Max, so
the speed and memory behaviour carries over; the Pro audio build's
free internal RAM after Bluetooth is the one thing not yet measured.
- HYN-touch Pro envs are untested (no v1.1/CST3530 hardware on hand);
to be marked experimental in the release notes.
Files: examples/companion_radio/{main.cpp, ui-new/GBCEmulatorScreen.{h,cpp},
ui-new/GamesMenuScreen.h, ui-new/UITask.{h,cpp}}, variants/lilygo_tdeck_pro/TCA8418Keyboard.h
Follow-up to the v1.14 emulator commits. T-Deck Max unless noted.
MEMORY AND STABILITY (GBCEmulatorScreen.cpp)
- Emulator task stack is now 8 KB, static, reserved at boot. Once
Bluetooth has been switched on in a boot its stack stays resident
(SerialBLEInterface::disable() never releases it) and a later game
launch could not find 12 KB of internal RAM in one piece. Measured
use is about 2 KB.
- Core context released on every failed launch, not just on quit; a
failure no longer holds 50 KB.
- No periodic full refresh during play (too distracting). The full
refresh on quit stays, to clear ghosting before the ROM list.
SAVES
- .sav written in the background: cart-RAM writes mark it dirty and
the UI task writes the file once the game has left its cart RAM
alone for 2 s, i.e. shortly after the user saves in-game. Quit
writes only if still dirty, and no longer draws and refreshes an
intermediate "Saving..." frame (that frame cost 650 ms by itself).
INPUT
- Both-shifts keyboard-backlight chord works mid-game: it is the one
key raw joypad mode lets through. The toggle body moved from
handleKeyboardInput() into toggleKeyboardBacklight() (main.cpp) so
the game and the normal path share one on/off state.
- On quit the keyboard stays in raw mode, still drained through the
panel's busy wait, until the ROM list has been drawn. Keys pressed
during the quit flash used to queue in the TCA8418 and replay as
navigation afterwards (one held Q ran four screens back).
PICTURE
- Game pictures after the first refresh only the 216-line game window
(GxEPDDisplay::requestWindowRefresh, consumed by endFrame). Measured
at 652 ms either way, the same as full-panel: the panel's waveform
time is the floor, so this saves data transfer only.
TYPING (main.cpp, all e-ink builds)
- COMPOSE_REFRESH_INTERVAL 700 -> 0. lastComposeRefresh is stamped
after the blocking e-ink refresh completes, so the interval only
added dead time on top of it. Worst-case keystroke-to-screen drops
from about 1.6 s to about 0.9 s. COMPOSE_TYPING_PAUSE unchanged.
GAMES MENUS
- Games menu and Game Boy ROM list rows follow the user's font size
and style via the NodePrefs helpers (as the channel picker does);
Max touch hit-test updated to match. Footers read Q:Back.
BUILD ENVS (Pro)
- meck_audio_wifi_hyn and meck_audio_standalone_hyn, the HYN-touch
counterparts of the existing meck_audio_ble_hyn.
Files: examples/companion_radio/{main.cpp, ui-new/GBCEmulatorScreen.{h,cpp},
ui-new/GamesMenuScreen.h}, src/helpers/ui/GxEPDDisplay.{h,cpp},
variants/lilygo_tdeck_max/TCA8418Keyboard.h,
variants/lilygo_tdeck_pro/platformio.ini
EMULATOR (T-Deck Max)
- Q now quits a running game, matching the back key used across the
rest of the interface. Shift+Backspace still works. Added as a second
exit latch in the keyboard driver's raw joypad mode; the on-screen
hint reads "Q: Quit".
variants/lilygo_tdeck_max/TCA8418Keyboard.h
examples/companion_radio/ui-new/GBCEmulatorScreen.{h,cpp}
README
- New "Game Boy / Game Boy Color Emulator (T-Deck Max, v1.14+)"
subsection under Games: what it is, where to get free homebrew ROMs
(uCity, Halo: Combat Devolved), where to put them (/roms, .gb/.gbc,
32 files, names under 48 characters), how to launch and play (key
table, radio paused and CPU at 240 MHz while a game runs), what the
picture looks like and why it updates about 1.4 times a second,
saves (.sav on quit, no RTC state), and the release's limits.
- Contents entry for the new subsection; Games intro mentions the
Games tile and the Max-only emulator.
- SD Card Requirements lists Game Boy ROMs and saves.
- T-Deck Max intro cross-references the emulator.
- Road-Map: emulator done on the Max; Pro support, ES8311 sound with
mic-key mute, and RTC save state listed as to-do.
- Third-Party Libraries: Peanut-GB (MIT, Mahyar Koshkouei) added, with
a note that no Game Boy software is bundled.
Version tags on the new items are v1.14; the global version bump
follows in the next commit.
Follow-up to the initial Game Boy emulator commit (T-Deck Max).
SPEED (GBCEmulatorScreen.cpp)
- Pacing keeps its deficit: a frame that finishes late is paid back by
running the next ones back-to-back instead of resetting the deadline
and forgiving the lost time, which held Pokemon Gold at 0.96x. Only a
stall of more than 250 ms resyncs. Now measures 1.00x on every 5 s
window. A 1 ms yield every 30 undelayed frames keeps the idle task
(and the task watchdog) fed.
- The core context (49952 bytes) is allocated from internal RAM for
the duration of a game and freed on quit, with PSRAM as the fallback
if no internal block is free; the launch log says which it got.
- Speed line printed to serial every 5 s (window fps, average, ratio to
real time).
INPUT (GBCEmulatorScreen.cpp, GxEPDDisplay.h)
- GxEPDDisplay::setBusyCallback() exposes GxEPD2's busy-wait hook. The
emulator registers a keyboard poll on it while a game runs, so key
presses and releases are seen through the ~650 ms panel refresh
instead of waiting for it to finish.
PICTURE (GBCEmulatorScreen.cpp, UITask.cpp, GxEPDDisplay.{h,cpp})
- 1.5x nearest-neighbour scale to 240x216, the full panel width,
centred; title line removed, quit hint kept.
- Ordered 4x4 Bayer dithering replaces the single threshold: the four
Game Boy shades map to 0, 6, 11 and 16 dark pixels in 16, so
sprites with mid-tone colours are no longer flattened to white or
black. The pattern is fixed to panel position so it does not crawl
between refreshes.
- UITask: the 800 ms minimum interval between e-ink refreshes is
lifted while a game runs, so pictures follow at the panel's own
partial-refresh rate (about 0.7 s).
- GxEPDDisplay::requestFullRefresh(): the next endFrame() uses the
full black/white waveform regardless of frame change. The emulator
requests one every 45 pictures (about 30 s) and once on quit, to
clear the residue that continuous partial refreshes leave on the
game screen and the home screen after it. No other screen calls it.
Files: examples/companion_radio/ui-new/GBCEmulatorScreen.{h,cpp},
examples/companion_radio/ui-new/UITask.cpp,
src/helpers/ui/GxEPDDisplay.{h,cpp}
MAPS FIX (all T-Deck Pro and Max builds)
Opening Maps from the home tile showed "SD card not found" until the G key
had been pressed once that boot. The map screen's SD flag was only set by
the G key handler; the touch tile and CardKB routes opened the screen
without it. The G handler's setup (SD flag, GPS position, contact markers,
CPU boost) is now openMapScreen() in main.cpp and all three routes call
it. G on the map (re-centre) is unchanged.
PLATFORMIO (variants/lilygo_tdeck_max)
- New meck_max_ble_garmin env for the Garmin watch companion: identical to
meck_max_ble with BLE_DEBUG_LOGGING, MECK_BLE_JUST_WORKS (no-passkey
pairing), MECK_BLE_SMALL_MTU_SPLIT (23-byte ATT frame slicing),
MECK_WATCH_EXT (watch extension commands) and MECK_BLE_SLOW_INTERVAL
switched on.
- meck_max_ble now has those five flags commented out, so the standard
phone-app build is isolated from the watch experiments.
GAME BOY / GAME BOY COLOR EMULATOR (T-Deck Max only in this build)
New "Game Boy" entry in the Games menu. Lists .gb/.gbc ROMs in /roms on
the SD card and runs them with the Peanut-GB core (same patched copy as
Meck-P4) in its own task on core 0 at the real 59.73 fps, drawing a
black-and-white snapshot to the e-ink at the panel's refresh rate.
- Keys: W/A/S/D d-pad, K = A, J = B, Enter = Start, Space = Select,
Shift+Backspace = quit (save written). No sound yet.
- Saves: .sav next to the ROM, written on quit.
- LoRa radio in standby and mesh loop paused while a game runs (reuses
the OTA pause). CPU held at 240 MHz.
- Keyboard polled through the e-ink busy wait so input is not delayed by
the ~650 ms refresh; the 800 ms refresh floor is lifted during play.
- Speed line printed to serial every 5 s.
Files:
- ui-new/GBCEmulatorScreen.{h,cpp} (new), ui-new/peanut_gb.h (new)
- ui-new/GamesMenuScreen.h: GAME_GBC entry
- ui-new/UITask.{h,cpp}: gbc_screen, goto/is/get, resetIdleTimer(),
no refresh floor while a game runs
- main.cpp: launch, exit and key routing
- variants/lilygo_tdeck_max/TCA8418Keyboard.h: raw joypad mode
- src/helpers/ui/GxEPDDisplay.h: setBusyCallback()
Pro builds compile unchanged (all emulator code is guarded).
- ChannelDetails gains scope_key[16]; MyMesh::setChannel derives it from
scope_name on every write (screens, serial, phone sync, boot load), so
sending copies bytes instead of doing a name lookup and derivation per
message. Port of the Meck Watch regions fix.
- getChannelScopeName now copies out instead of returning a pointer into
a local (dangling; caused intermittent unscoped sends).
- BLE small-MTU slices become [tag][len][payload] (18 payload bytes) so
stream transports (nRF52) can find slice boundaries; same format on
ESP32 for one dialect across nodes and the Garmin app.
- New MECK_BLE_SLOW_INTERVAL flag: request a 100-200 ms connection
interval instead of 15-20 ms for the watch build.
Canned messages (T-Deck Max only):
- NodePrefs gains canned_msgs[10][134] as the final field; DataStore load is short-read tolerant (older prefs upgrade to empty slots), NUL-forced, appended in savePrefs. Storage is shared across boards so the prefs layout stays uniform; the Settings entry point is gated to the Max.
- Settings -> Canned Messages: ten slots, full-length inline editor (tail + n/133 counter); Enter commits, empty clears, Sh+Del cancels. T5S3 VKB path exists behind the same gate.
- Channel screen overlay: the speech-bubble pad toggles the list on a channel or DM conversation; tapping a row sends via sendComposedMessage() (channel -> that channel, DM conversation -> DM to that contact); all-empty shows an alert. Other screens keep the channel-picker action.
- Post-test fixes: tap intercept moved ahead of the vy<18 go-home rule that ate row taps and left the overlay stuck; any keyboard key closes the overlay in handleKeyboardInput (keys never reach ChannelScreen::handleInput on Pro/Max); setViewChannelIdx resets overlay state like the path overlay.
40 MHz extreme-battery test builds: meck_max_standalone_40mhz, meck_audio_standalone_40mhz, meck_4g_standalone_40mhz. CPU idle/boost/low-power all 40 MHz; MECK_40MHZ_TEST gates the modem (forced off, config kept), GPS (rail off, page hidden), browser/OTA, alarms, audio features and notification MP3s; gated tiles dither and go inert; MESH_DEBUG=1. The Pro envs deliberately re-run the March 80->40 TCA8418 config (noted in env comments).
T-Deck Pro v1.1 HYN touch (meck_audio_ble_hyn, Meck v1.12.6.HYN): opt-in MECK_PRO_HYN_TOUCH switches touch to the vendored Hynitron driver, auto-detecting CST3530/CST328 at 0x1A. Seven driver guards widened; XL9555 callbacks stay Max-only; explicit config SDA13/SCL14/RST38/INT12; the manual GPIO38 reset pulse is suppressed (driver self-resets); readTouch and the 4G dialer dispatch widened. Link fix: ui-new/*.c added to the env src filter (the cst66xx/cst3xx/cst226se providers were not compiled). Confirmed working by an affected v1.1 (CST3530) user.
Pro audio builds: the full-width Phone tile is no longer rendered (no modem; its tap was already inert).