Commit Graph
23 Commits
Author SHA1 Message Date
sim1988son 539271f293 Add Simpson board support 2026-10-15 20:39:48 +02:00
JakubandClaude Opus 5.5 8c20914689 refactor(ui): upstream's UIColor palette in place of the DARK/LIGHT enum
- DisplayDriver takes ColorVal; each driver's .cpp defines the UIColor roles
  (window_bkg, primary_txt, ...) in its own values. ui-new draws in two:
  window_bkg and primary_txt. OLED and e-ink look as before (sim screens
  pixel-identical).
- E213, E290, LGFX, Null, ST7735, ST7789LCD, U8g2 taken whole from upstream
  (with them the rewritten ST7735 driver and the Heltec V4 R8 TFT display).
- SH1106, SSD1306, ST7789, EinkGfxDisplay and the sim drivers converted.
- ui-orig, ui-tiny, simple_* get upstream's colour roles; the repeater's UI
  taken from upstream (its power-off screen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:42:04 +02:00
JakubandClaude Opus 5.5 061e5ba36b feat(l1): Home pages slide sideways, the page pill glides along
DisplayDriver gains slideBegin()/slideCompose(): the driver keeps the frame
on screen and, in the next one, moves it out while the new rows follow.
SH1106 does it on its 1 KB buffer (+1 KB RAM for the copy), the sim on its
canvas; drivers that can't read their frame back keep cutting over (e-ink).

Home slides the content below the page-icon row in 220 ms with an ease-out
(the whole screen to and from the header-less clock), and the current-page
pill glides between icons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:08:40 +02:00
JakubandClaude Opus 5.5 0c739992bb perf(l1): OLED sends only the parts of the screen that changed
Each frame is hashed per 32-column block of each 8-px page and only changed
blocks go over I2C. A full frame was 1 KB / 31 ms on every change; a moved
selection, a scrolling name or a clock tick is now 1-8 ms. 128 B of hashes,
no frame copy; full sends stay for wake/clear and SPI panels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:01:53 +02:00
MarekZegare4 68527e7ba0 Merge upstream companion-v1.17.1 into power-saving
Pulls in real fixes: scoped-reply routing, RX boosted-gain restored
correctly after AGC reset, T-Echo Lite/Card SPI pin corrections
(unused pins now map to NRFX_SPIM_PIN_NOT_USED via 0 instead of -1)
and TCXO voltage fix, Heltec T096/T1 and MeshPocket pin fixes,
T-beam Supreme S3 display fix, LR2021 preamble/IRQ timeout handling.

None of the touched variants overlap with our active Heltec V3/V4,
Cardputer ADV, GAT562, or WioTracker builds.

# Conflicts:
#	examples/companion_radio/MyMesh.cpp
#	examples/companion_radio/MyMesh.h
#	examples/companion_radio/NodePrefs.h
#	src/helpers/radiolib/CustomSX1262Wrapper.h
#	src/helpers/radiolib/RadioLibWrappers.cpp
#	src/helpers/ui/SH1106Display.cpp
#	variants/lilygo_techo_lite/platformio.ini
#	variants/lilygo_techo_lite/variant.h
2026-08-14 15:58:23 +02:00
Wessel Nieboer 32bd6d48d6 Fix T-beam Supreme S3 display 2026-08-10 13:39:16 +02:00
JakubandClaude Opus 5 f8b9e1acb8 feat(oled): misc-fixed 6x9 font on SSD1306 too, for GAT562 30S solo
The misc-fixed font (full Latin/Greek/Cyrillic) had only ever reached
SH1106Display and the e-ink driver. GAT562 30S -- like 24 other variants
-- uses SSD1306Display, which stayed on the built-in 5x7 font, so every
keyboard alphabet beyond ASCII and every accented contact name was
transliterated (Łódź -> Lodz) or drawn as a filled block.

Extract the renderer into MiscFixedRenderer.h rather than copying it:
Adafruit_SH110X and Adafruit_SSD1306 both derive from Adafruit_GFX and
glyph drawing is pure pixel plotting, so one implementation serves both
drivers (-79 lines from SH1106Display.cpp, same flash usage as before).
The header is .cpp-only by contract -- the font tables are static const,
so including it from a driver header would land a copy in every
translation unit.

On SSD1306 the path is opt-in behind OLED_MISC_FIXED_FONT, set only in
the two GAT562 30S solo envs: the font costs ~14 KB of flash and the
other 24 variants' repeater/companion builds have no keyboard to type
those alphabets on. Without the flag that driver is unchanged, verified
by building GAT562_30S_Mesh_Kit_repeater.

Drive-by consistency fix from the extraction: a newline in print() now
advances the cursor by yAdvance * text_size instead of a single yAdvance,
which was half a row short at setTextSize(2). The e-ink driver always
scaled it. No effect at size 1, which is everywhere the UI prints '\n'.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 22:48:06 +02:00
Scott Powell 3857f45826 * monochrome displays now do _not_ invert titlebar 2026-07-24 15:14:56 +10:00
Scott Powell b8504e55c6 * refactor of Color mapping in UITasks / DisplayDrivers
* color displays now with a new light theme
2026-07-22 16:03:33 +10:00
=UltimateCodeWarrior 0de2b4fc5f Move Supreme OLED address to variant config
Keep SH1106Display generic by relying on DISPLAY_ADDRESS while the T-Beam Supreme variant declares its 0x3D OLED address.
2026-07-20 19:24:38 -07:00
JakubandClaude Sonnet 5 273fbfde7a chore: pre-release cleanup pass (Lemon-era naming, bot sender parsing dedup)
Renamed the vestigial Lemon/default font-switch naming (setLemonFont/
isLemonFont/drawLemonChar/lemonXAdvance/_use_lemon -> setSingleFont/
isSingleFont/drawGlyph/glyphXAdvance/_single_font) across DisplayDriver.h
and both concrete drivers -- both have been permanently single-font for
several commits, so the old names invited a future reader to think a
real switch still existed. Pure identifier rename, no logic changed.

Also extracted the byte-identical "SenderName: " prefix-splitting in
MyMeshBot.h's tryBotReplyChannel()/tryBotChannelCommand() into a shared
botChannelSenderSplit(), mirroring the existing botRoomSenderName().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 21:02:33 +02:00
JakubandClaude Sonnet 5 fe1e0d29ce fix(display): undefined-glyph box overlapped the line above on OLED
drawLemonChar()'s "y" is the top of the current text row on SH1106 (real
glyphs render at y + 7 + yo + row), unlike GxEPDDisplay's version, where
y IS the baseline. The undefined-glyph fallback box copied GxEPD's
y - 7*sz formula verbatim during the font-unification pass, sending it
7px above the row's top edge -- into the previous line's space. Drawing
it at plain y (already baseline minus the font's 7px ascent) lands it in
the same relative position GxEPD's version occupies, within its own row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 20:53:56 +02:00
JakubandClaude Sonnet 5 453dc5e570 feat(admin): typed Radio/Routing field editors; pre-release audit fixes
Tools > Admin: split the Radio tab's single "f,bw,sf,cr" comma-string
field (free-text keyboard) into 4 independent, type-appropriate rows --
Frequency (same digit-cursor DigitEditor Settings/Repeater use locally),
Bandwidth/Spreading factor/Coding rate (discrete-set LEFT/RIGHT stepping),
plus TX power and the 3 Routing numeric fields as number steppers and
Repeat as an ON/OFF toggle. Edits happen locally (zero mesh traffic per
keystroke); only Enter sends one combined `set`, Cancel sends nothing.

Full pre-release audit of all 16 commits since v1.22 (5 parallel focus
areas: display/font, keyboard/messages, Nodes/Admin, Bot/channels,
UITask+NodePrefs schema) turned up and fixed:

- Admin: fetched FK_NUMBER values weren't clamped to the field's range,
  so a value already out-of-range could get stuck unreachable; fixed
  commit-time float format noise (%.6f -> %.3f); Cancel/failed-login
  always returned to the Nodes picker even when Admin was opened
  directly from a node's Hold-Enter action -- now returns to wherever
  it was actually opened from (AdminScreen::_from_picker).
- Keyboard: one-shot Shift was consumed after the *first* T9 multi-tap,
  so cycling to the 2nd/3rd candidate always came out lowercase --
  fixed by caching the cycle's caps state (t9_caps).
- Messages: history is numbered newest-first, so a message arriving
  while scrolled up to an older one silently relabeled the view onto a
  different message -- selection now shifts with the insert.
- Channels: onChannelRemoved() didn't clear ch_notif_override/
  ch_notif_muted/ch_fav_bitmask despite its own contract comment
  requiring it (now far more reachable via the on-device Delete);
  an all-zero hex secret silently self-deleted the channel it was
  just saved into (collides with the empty-slot sentinel) -- rejected.
- Room login: isRoomLoggedIn() indexed the login-tracking ring
  directly instead of via its head offset, silently wrong once the
  ring wraps (8+ rooms/session) -- the new on-device Logout depends
  on this being right.
- Font/display: removed the now fully-inert Settings > Display > Font
  toggle and the dead LemonFont.h (retired by the earlier misc-fixed
  font unification, zero remaining includes); fixed a copy-pasted
  "5x7" comment (font is 6x9), two meaningless dead ternaries, and an
  OLED/e-ink inconsistency in the undefined-glyph fallback box offset.
- AdminField's `kind`/bounds fields no longer rely on default member
  initializers inside aggregate-init: this toolchain's actual nRF52
  build (unlike env:native) has no explicit -std= override, so it
  predates C++14's aggregate-with-default-member-initializer rule.
  Given an explicit constructor instead -- portable regardless of
  standard, all existing field-table literals unchanged.

Docs updated to match: tools_screen.md (Diagnostics as a 3-tab
carousel, was documented as one flat screen), message_screen.md
(chat bubbles, newest-at-bottom, cursor mode, secret validation),
settings_screen.md (dropped the dead Font row), solo_ui_framework.md
(header menu_hint signatures, icon priority-drop, KeyboardWidget's
T9/alphabets/cursor-mode). release-notes.md gains the v1.23 section
covering all of the above plus the other 15 commits since v1.22.

Build-verified on WioTrackerL1_companion_solo_dual.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 19:38:51 +02:00
JakubandClaude Sonnet 5 82caa3e292 feat(ui): unify OLED on misc-fixed 6x9 font; add Diagnostics tab carousel
Replace the Lemon/default font-switch with a single misc-fixed 6x9 font
(full Latin/Greek/Cyrillic coverage), generated via a new tools/bdf2gfx.py
BDF-to-GFX converter. Removes the keyboard's per-render font-switch
workarounds now that one font fits its cell cleanly.

DiagnosticsScreen becomes a circular tab carousel (Live / System / Font),
adding a firmware+device+radio info tab and a per-alphabet rendering test
card covering every keyboard language.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 11:16:25 +02:00
JakubandClaude Opus 4.8 4ae3d22654 perf(oled): skip I2C flush when the frame is unchanged
The SH1106 path always pushed the full 1 KB buffer over I2C every endFrame,
even on static screens (clock, home) that don't change between updates. Hash
the GFX buffer (FNV-1a, no external dep — the CRC32 lib is only wired into
e-ink builds) and skip display.display() when it matches the last frame
pushed. _force_redraw forces a flush on the first frame and after
turnOn()/clear() so a post-wake or post-clear frame can't be wrongly skipped.

Mirrors the existing e-ink CRC-skip. Builds green: WioTrackerL1_companion_solo_dual.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 22:40:01 +02:00
UltimateCodeWarriorand=UltimateCodeWarrior b8b6598dd3 Fix blank OLED on T-Beam Supreme V3 (I2C bus + 0x3D address)
The SH1106 OLED on the LilyGo T-Beam Supreme V3 never lights up because:

1. The primary I2C bus (Wire) that the OLED, BME280 and magnetometer share
   is never initialized. The PMU/RTC use Wire1 (via XPowersLib); nothing
   brings up Wire on PIN_BOARD_SDA/PIN_BOARD_SCL, so the display driver
   talks on the wrong default pins.
2. The OLED is at I2C address 0x3D on this board (0x3C is taken by the
   QMC6310 magnetometer), but SH1106Display::begin() only tried 0x3C.

Initialize Wire for TBEAM_SUPREME_SX1262, and have SH1106Display::begin()
prefer 0x3D (only ever used by the OLED) before falling back to 0x3C.
Backwards-compatible for boards with the OLED at 0x3C.

Closes #2609
2026-06-22 23:39:34 -07:00
JakubandClaude Sonnet 4.6 52a7081a13 refactor(ui): dedupe UTF-8 codepoint decoder
Three copies of the same routine: DisplayDriver::decodeCodepoint (added
in the FullscreenMsgView wrap fix) plus per-driver duplicates in
SH1106Display and GxEPDDisplay. Consolidate on DisplayDriver and have
translateUTF8Static also route through it instead of its own inline
decoder. Net: 63 lines removed, single source of truth.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:25:35 +02:00
JakubandClaude Sonnet 4.6 b279b95b2d refactor(ui): apply code review fixes — bugs, risk, optimisations, cleanup
Fixes 7 bugs (timing UB on unsigned long, abs() no-op, XBM CRC PROGMEM
scan, CayenneLPP heap thrash ×2, UTF-8 reply prefix, lock-seq reset on
wake), 3 risk items (notif melody stop guard, bot trigger pre-lowercase,
lock-seq cleared on display wake), plus optimisations (fmtMsgAge/
getTextWidth caching, RTTTL builder consolidated to NodePrefs, HP_*
constants and homePageLabel table moved to NodePrefs, DataStore flat
lambda schema, translateUTF8Static factored out) and minor cleanup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:03:45 +02:00
JakubandClaude Sonnet 4.6 fa842b202a fix: scale Lemon font glyphs with setTextSize on lock screen clock
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:34:24 +02:00
JakubandClaude Sonnet 4.6 a115916d8f feat: runtime font switcher — Default vs Lemon in Settings > Display
- Add Lemon font (LemonFont.h, LemonIcons.h) to the standard build
  alongside the Adafruit built-in font; ~101 KB added to flash
- SH1106Display: add _use_lemon flag + setLemonFont(bool) to switch
  at runtime; print() and getTextWidth() use Lemon path when active;
  translateUTF8ToBlocks() passes UTF-8 through unchanged (Lemon supports
  full Unicode U+0020-U+04FF) vs transliterating for the default font
- DisplayDriver: add getCharWidth()/getLineHeight() virtuals (defaults 6/8);
  SH1106Display returns 5/9 for Lemon, 6/8 for default; add setLemonFont()
  no-op virtual; fix orphaned UTF-8 leading byte in drawTextEllipsized
- FullscreenMsgView: replace fixed-char-count word-wrap with pixel-accurate
  wrap using display.getTextWidth(); use getLineHeight() for spacing so
  Lemon (9 px) and default (8 px) both render correctly
- NodePrefs: add use_lemon_font field (0=default, 1=Lemon)
- SettingsScreen: add "Font" item in Display section (Default / Lemon),
  calls UITask::applyFont() on change
- UITask: add applyFont() that calls display->setLemonFont(use_lemon_font);
  called at startup (begin()) and when the setting changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:33:35 +02:00
JakubandClaude Sonnet 4.6 861a65d4b1 Fix buzzer notifications, unread tracking, OLED dimming; remove dead code
- MyMesh: notify() now always fires for channel/contact messages regardless
  of serial connection; called after addChannelMsg so channel index is set
- ChannelHist: fix unread watermark direction (histEntry is newest-first,
  index 0=newest); counter now decrements correctly as user reads messages
- ChannelHist: reset unread to 0 after sending (user is active in channel)
- SH1106Display: add pre-charge register (0xD9) to setBrightness for wider
  dimming range; re-apply contrast+precharge in turnOn(); tune curve
- UITask: remove MsgPreviewScreen dead code (~180 lines, never shown)
- UITask: fix strcpy→snprintf in showAlert()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:09:47 +02:00
JakubandClaude Sonnet 4.6 c3846ba9f5 feat(wio-tracker-l1): add settings screen and companion radio improvements
Settings screen (UI_HAS_JOYSTICK_UPDOWN build variant):
- Display brightness (5 levels, contrast curve tuned for SH1106 non-linearity)
- Buzzer on/off (respected at startup, no more forced unmute)
- TX power (2–22 dBm)
- Auto-off delay (5s / 15s / 30s / 60s / never)
- GPS update interval (off / 30s / 1min / 5min / 15min / 30min)
- Timezone offset (UTC-12..+14) for clock screen
- Low battery auto-shutdown threshold (off / 3.0–3.5V, default 3.4V)
- Battery display mode (icon / % / voltage)

Battery:
- EMA filter (alpha=0.2) on ADC readings to smooth voltage spikes from uneven load
- Battery % calculated using low_batt_mv as 0% anchor
- Mute icon repositions dynamically based on battery display width

Clock screen on HomeScreen showing time/date with timezone support.

Build:
- _settings variants added for USB and BLE companion radio builds
- Automatic UF2 generation on every build via create-uf2.py post-script
- UI_HAS_JOYSTICK_UPDOWN flag guards joystick_up/down to avoid breaking other boards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:09:46 +02:00
Rob Loranger 25b534a29d add support for SH1106 OLED display 2025-05-16 08:45:55 -07:00