4673 Commits
Author SHA1 Message Date
ripplebizandGitHub 140178728b Merge pull request #3427 from Dom4n/feat/lr1110-dcdc-dev
Enable DC/DC for LR1110 radios
2026-09-22 17:57:09 +10:00
ripplebizandGitHub a76d511ff4 Merge pull request #3131 from liekmarflow/feature/board-api-hooks
Add board loop hook for periodic work
2026-09-22 16:43:18 +10:00
Wolfram Keil 61be70849a Add board loop hook for periodic work 2026-09-22 08:01:48 +02:00
ripplebizandGitHub 5e9d80df38 Merge pull request #3464 from lbibass/lr1121_dcdc
LR1121 DC-DC & Misc Updates
2026-09-22 15:12:56 +10:00
ripplebizandGitHub 7faf87682c Merge pull request #3469 from Blake-Latchford/issue/3409/constrain-agc-interval
Constrain `agc.reset.interval` and allow intervals > 255s
2026-09-22 15:03:03 +10:00
Blake Latchford 0c3fe356d0 Constrain agc.reset.interval and allow intervals > 255s 2026-09-21 12:26:36 -04:00
fdlamotteandGitHub be371634d0 Merge pull request #3468 from weebl2000/thinknodem4_fixes
Thinknode m4 - don't touch crystal and OTA name
2026-09-21 11:09:55 -04:00
Wessel Nieboer b5787757a7 Thinknode m4 - don't touch crystal and OTA name 2026-09-21 15:55:44 +02:00
fdlamotteandGitHub f4ae72dc12 Merge pull request #3436 from Blake-Latchford/wio-e5-fix
WIO-E5 Fix: Pin Radiolab for stm32 and replace ltoa
2026-09-21 05:50:12 -04:00
ripplebizandGitHub 65737d48f4 Merge pull request #3402 from meshcore-dev/sensor-improvements
Sensor improvements
2026-09-21 19:03:18 +10:00
Ev Lbibass 84f1e11d29 update structure of LR1121 to match LR1110 files. Implement DC-DC on LR1121 radio. saves about 30% power consumption at idle. 2026-09-20 20:38:05 -04:00
fdlamotteandGitHub f8f9bd4daf Merge pull request #3463 from fdlamotte/thinknode_m4
Thinknode m4
Doing the merge now as it doesn't touch anything outside its own variant dir and its board file ;)
2026-09-20 16:22:47 -04:00
Florent 8bf072a6f0 M4: Handle poweroff 2026-09-20 16:13:15 -04:00
Florent 0a15c487d8 m4: inital port 2026-09-20 15:25:18 -04:00
Blake Latchford 12a8c8d4d4 Add missing include, and revert removal of lota 2026-09-20 15:16:33 -04:00
JakubandClaude Sonnet 5 f8cd24dd4d fix(ui): keep the hop/ack marker clear of the age on long sender names
The marker was placed after the sender's full width while the name itself
was only ellipsized against the age, so a long name pushed the hop count
(worst with two digits) onto the age. The name now yields to the marker and
the age, the marker follows the width the name actually got, and a 2px gap
separates marker from age.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 20:18:25 +02:00
Liam CottleandGitHub 0886259701 Merge pull request #3108 from tjdownes/muzi-base
Add Muzi Base board support (Duo + Uno + SuperIO)
2026-09-20 22:56:32 +12:00
TJ DownesandAudit Bot 114cf9f4fc Use the default BLE TX power on Muzi Base
Drop BLE_TX_POWER=0 from the companion envs so they use the default of
4 dBm, like most other variants. The lower power was carried over from
the original Base Duo PR and real-world range is better at the default.
2026-09-20 03:46:25 -07:00
ripplebizandGitHub b37e7dd955 Merge pull request #3431 from meshcore-dev/abstract-ui-overhaul
Abstract UI overhaul
2026-09-20 18:08:29 +10:00
TJ DownesandAudit Bot 798ce636df Address review feedback on Muzi Base support
- rename the board class and files to MuziBaseBoard
- uppercase the build flags (MUZI_BASE, MUZI_BASE_SUPERIO)
- name the superIO envs muzi_base_{duo,uno}_superIO_companion_radio_ble so
  build.sh picks them up
- set MAX_CONTACTS to 350 like the other variants
- move the pin setup from initVariant() into MuziBaseBoard::begin()
2026-09-19 21:47:24 -07:00
Liam CottleandGitHub 4d9a292084 Merge pull request #3459 from liamcottle/board/thinknode-m7-wifi
Add wifi support to ThinkNode M7 BLE variant
2026-09-20 15:25:08 +12:00
liamcottle 4021a341f8 add wifi support to thinknode m7 ble variant 2026-09-20 15:11:21 +12:00
Liam CottleandGitHub fac7bf5dd3 Merge pull request #3458 from liamcottle/cli/wifi-pwd
Allow fetching configured wifi password via companion cli
2026-09-20 14:34:48 +12:00
liamcottle 73afe3a0f5 allow fetching configured wifi password via companion cli 2026-09-20 14:22:13 +12:00
Liam CottleandGitHub e94125987e Merge pull request #3445 from mojoaxel/patch-1
docs: fix frame format tables
2026-09-20 10:26:16 +12:00
fdlamotteandGitHub 2c700d1689 Merge pull request #3449 from IoTThinks/MCdev-KeepLEDOffBeforePowerOff-20260919
Off LED before powering off for repeaters
2026-09-19 15:06:17 -04:00
JakubandClaude Sonnet 5 4af6d7d013 feat(live-share): own scope for [LOC] posts and time-limited sessions (#23, #24)
- Live Share gets a "Scope" row (Target / * / any scope from the shared
  list). It applies to [LOC] sends only, beats the app's send_scope and a
  channel's own pick, and never touches normal messages. Target keeps the
  previous behaviour. removeScope() fixes the stored index up.
- Auto share now always ends: "Stop after" 1/2/4/8/12 h (default 1 h, no
  unlimited option). On expiry it switches itself off and shows "Live share
  ended". The session clock is RAM-only, so a reboot starts a new session.
- NodePrefs: loc_share_scope + loc_share_duration_idx appended, sentinel
  0xC0DE002C -> 0xC0DE002E, sizeof unchanged (2824).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 14:22:27 +02:00
JakubandClaude Sonnet 5 dafd6c1266 ci(sim): show the real version in the WASM demo's splash
build_wasm.sh now takes FIRMWARE_VERSION (tag name for a release,
dev-<commit> otherwise) exported by build-solo-sim.yml, so the live demo
no longer falls back to "dev-<compile date>" on tagged releases.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 14:22:27 +02:00
JakubandClaude Sonnet 5 d49acc4e55 fix(ui): age messages from the device clock, not the phone's timestamp
A DM/channel post sent from the phone app was mirrored into the device history
with the app's timestamp. A phone clock ahead of the device's (or on local
time) made "now - timestamp" negative, which fmtAgeShort clamps to 0, so the
age sat at "0s" until the device clock caught up.

MessageHistory::displayTimestamp(): outgoing entries use the device's own
clock (they were sent just now); incoming entries with an unknown or future
sender timestamp use receipt time. Sender timestamps still drive incoming
dedupe and resends (msg_ts is untouched); an on-air timestamp is unchanged.

Release notes: add this fix, and say "older than v1.27" for the prefs cleanup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.28
2026-09-19 13:19:46 +02:00
JakubandClaude Sonnet 5 dff56a3c53 fix(companion): restore the v1.27 -> v1.28 scope migrations
eed6d31d dropped two one-time migrations as "old cruft", but both are needed
by exactly the upgrade path this release ships: v1.27 has sentinel 0xC0DE002A
and the scope list is new in this cycle.

- loadScopeList() again turns an existing single default_scope_name/key into
  list entry 1 (default) and MyMesh::begin() seeds the channels that already
  exist with it. Without it an upgrader's DMs and channels silently go out
  unscoped, contradicting the release note.
- loadPrefsInt() again zeroes repeat_extra_scope_mask/ch_scope_idx when the
  file predates 0xC0DE002B, so the old sentinel tail can't read back as real
  scope picks.

The older-than-v1.27 backfills stay removed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:19:46 +02:00
JakubandClaude Sonnet 5 745aefcee1 fix(radio): init SX1262 at a safe power on boards with an external-PA curve
95e3cf26 raised LORA_TX_POWER to 30 for the GAT562 30S, but CustomSX1262 passed
it straight to RadioLib's begin(), whose setOutputPower() rejects anything over
22 dBm (ERR_INVALID_OUTPUT_POWER) -- so radio init would fail on that board.
With NUM_PA_POINTS/TX_GAIN_LORA defined, LORA_TX_POWER is a radiated power, not
a chip register value: init at register 0 and let RadioLibWrapper::setTxPower()
apply the real power through the curve right after (companion applyApc(),
repeater setTxPower at begin). Other boards are unchanged.

Verified by build (GAT562 30S companion + repeater, Heltec V3 repeater) and by
reading RadioLib's SX1262::checkOutputPower(); not tested on hardware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:19:46 +02:00
JakubandClaude Sonnet 5 b3e3bae21b fix(ui): refuse adding a channel whose secret already exists
The on-device "+ Add channel" flow (Public quick-add, Hashtag, Private) wrote
to the first free slot with no check, so a second Public -- or any channel
already present -- could be added, giving the same on-air channel two list
entries with split history/unread state. A channel's identity is its secret,
not its name, so ChannelsView now rejects a save whose 16-byte secret is held
by a different slot. Edit skips its own slot, so renaming still works. Public
quick-add says "Already added"; the forms say "Channel already exists" and stay
open. App-side CMD_SET_CHANNEL and already-saved duplicates are untouched.

Verified: sim_companion_radio builds; in the WASM sim, adding Public with
Public present shows the alert and leaves one entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:01:41 +02:00
JakubandClaude Sonnet 5 461107e31e fix(ui): keep a gutter beside chat bubbles; docs + release notes catch-up for v1.28
- Message bubbles are capped at the row width minus a gutter (2 char widths,
  min 8px) so a long message no longer fills the whole row and loses the
  left/right anchoring that shows who sent it. Body wrapping uses the capped
  width. DM and channel history.
- Docs: shared scope list (Settings, Repeater Extra scopes, channel Scope row),
  contact Expire / Prune now, history hop count / wrap / scope tag, external
  PA TX curve build flags.
- release-notes.md: v1.28 gains GAT562 30S TX power, Heltec V3/V4 joystick
  Enter fix, prefs-migration removal note, and the bubble gutter fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 12:58:37 +02:00
Scott Powell 64434c5326 * misc 2026-09-19 20:13:18 +10:00
Kevin Le c425648bfc Off LED before powering off for repeater 2026-09-19 11:26:42 +07:00
Alexander WunschikandGitHub 448d1b2239 docs: fix frame format tables 2026-09-18 16:59:26 +02:00
Scott Powell 843598724c * fix for X1 2026-09-18 19:03:20 +10:00
JakubandClaude Sonnet 5 1981826a85 fix(heltec_v3/v4): user_btn needs pull-up + multiclick=false in joystick mode
With UI_HAS_JOYSTICK, user_btn (Enter) was left with pulldownup=false and
multiclick=true (the plain-PRG-button defaults), instead of matching the
other wired joystick contacts. Two effects on a wired Enter button:

- No internal pull-up on the Enter pin, unlike the direction/back contacts.
- multiclick=true buffers a click for ~280ms waiting for a possible double/
  triple click, but UITask.cpp's UI_HAS_JOYSTICK loop only ever checks
  user_btn for CLICK/LONG_PRESS — so a quick double-tap collapses into a
  DOUBLE_CLICK event that's silently dropped, making Enter feel laggy and
  unreliable.

wio-tracker-l1 (factory joystick) already builds user_btn with
pulldownup/multiclick matching its other contacts; apply the same pattern
here, conditional on UI_HAS_JOYSTICK so the stock external-pull-up PRG
button path (no joystick) is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-18 09:57:29 +02:00
Liam CottleandGitHub 166f75c1b6 Merge pull request #3442 from liamcottle/feature/companion-cli-commands
added reboot, shutdown and poweroff to companion cli commands
2026-09-18 18:25:33 +12:00
liamcottle 242e401a2c added reboot, shutdown and poweroff to companion cli commands 2026-09-18 18:17:52 +12:00
Blake Latchford 8d2a5657ac Pin Radiolab for stm32 and replace ltoa
The major rev from 19.x to 20.x breaks Radiolab, so pin it for now. This should fix the failing wio-e5-mini_repeater builds.

ltoa is removed upstream, so it was replaced with snprintf. The p[] buffer is always 16 bytes. Copy/paste for why claude thinks this is fine below, but also if this is broken it wouldn't be new.
```
exp2 in [23, 30] (int_part = mantissa << (exp2 - 23)): this is where int_part can reach its true max, up to 2,147,483,520 — 10 digits. That's what the snprintf bound of 11 (10 digits + NUL) is sized for. But in this branch frac_part is never assigned anything other than its initial 0, so only *p++ = '0' runs for the fraction — 1 char, not 7.

exp2 in [0, 22] (int_part = mantissa >> (23 - exp2)): this is the only branch where frac_part can also be nonzero and enter the 7-digit loop. Here int_part < 2^23 by construction, so it's capped at 7 digits, never 10.
```
2026-09-17 22:12:53 -04:00
Liam CottleandGitHub 3244e3ec13 Merge pull request #3382 from Blake-Latchford/wifi-disconnect-reason-logging
Extend WiFi disconnect logging to specify reason
2026-09-18 12:01:30 +12:00
Blake Latchford 1077331e31 Extend WiFi disconnect logging to specify reason
Today if a user builds firmware with an incorrect WiFi SSID or password,
they get a generic `WiFi disconnected.` error message.

Extend logging to descirbe the reason that WiFi was disconnected.

I gathered the updated logs for the 3 scenarios below.

```
WiFi: Attempting manual WiFi reconnect...
WiFi: WiFi disconnected (reason=ASSOC_LEAVE). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
```

```
WiFi: WiFi disconnected (reason=NO_AP_FOUND). Flagging for reconnect...
```

```
WiFi: WiFi connected successfully!
WiFi: Got connection
```
2026-09-17 19:39:51 -04:00
JakubandClaude Sonnet 5 eed6d31d42 refactor(companion): drop one-time prefs-migration cruft, fix stale Msg wake comments
loadPrefsInt()'s "sentinel mismatch" block had accumulated ~62 lines of
one-shot backfills tied to specific old NodePrefs::SCHEMA_SENTINEL values
(favourites/map home-page bits, split bot-command toggles, trail_units_idx,
bot_trigger_ch seed, scope mask/index zeroing). Reduce it to just the
sentinel read + mismatch log line -- an upgrade from a version old enough
to hit any of these now lands on today's plain defaults for that field
instead of a silently-seeded value, same outcome a fresh device already
gets. The ongoing per-field range clamps (defensive against any corrupt or
out-of-range byte, not version-specific) are untouched.

Same treatment for DataStore::loadScopeList()'s one-time synthesis of a
scope-list entry from the old single default_scope_name/key field: removed,
along with the scope_migrated_legacy plumbing in MyMesh::begin() that only
ran once that migration had just fired. loadScopeList() drops its now-
unused NodePrefs parameter and bool return.

Also trimmed ~25 per-field comments that over-specified which exact old
sentinel produced which stray byte, down to what the clamp actually
defends against -- except where the hex value explained a genuinely
non-obvious byte-aliasing interaction, which stays. One comment (scope
mask/index) was flagged and rewritten because it described the very
zeroing logic this change removes.

Drive-by: two comments still said Settings > Sound > "Msg wake" -- it's
been under Settings > Display for a while, per the enum's section grouping
in SettingsScreen.h.

Verified: sim_companion_radio and WioTrackerL1_companion_solo_dual build
clean, RAM/Flash usage unchanged (pure logic removal, no schema/layout
change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 15:41:26 +02:00
Scott Powell b3b17025e3 * more MyMesh::Listener interface hooks 2026-09-17 17:33:36 +10:00
Scott Powell 30dd723c26 * MyMesh::begin() refactor, removing last display concepts 2026-09-17 14:25:41 +10:00
Liam CottleandGitHub cdd0407711 Merge pull request #3430 from liamcottle/fix/3429
Add missing null display driver class for ThinkNode M7 ethernet variant
2026-09-17 15:54:28 +12:00
liamcottle cd54ee9754 add missing null display driver class for thinknode m7 ethernet variant 2026-09-17 15:52:46 +12:00
Scott Powell 5c3d9281ff * refactored the UI_DISCOVER_* feature 2026-09-17 13:45:33 +10:00
Jarosław Domański b71933beb5 Enable DC/DC in shared LR1110 initialization 2026-09-16 22:43:48 +02:00