Select nodes had this flag enabled, testing by the community
and hardware specs indicate this can be enabled global for all
node types using this chipset.
Any nodes down the line that may be quirky can be individually
disabled with `-U USE_CC310_HW_CRYPTO`.
CardKB is level-triggered (repeats the held byte every poll) and its Enter
key collided with the on-screen keyboard grid's own commit action, causing
duplicate characters and accidental message sends. Debounce polling and use
the CardKB v1.1 Fn modifier (confirmed working on real hardware) instead of
tracking navigation state: plain Enter now behaves like the physical centre
button, Fn+Enter submits, Fn+Tab opens the Hold-Enter equivalent, and
Fn+<letter> opens that letter's accent popup directly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Auto-detected at boot on Wire1/Grove (addr 0x5F) -- no setting to flip, and a
no-op on boards without that bus or with nothing attached. This UI's key
codes (KEY_LEFT/UP/DOWN/RIGHT/ENTER/CANCEL) already match CardKB's own byte
protocol, so most input needs zero translation and flows through the same
key queue as physical buttons.
Two bytes get remapped in UITask::pollCardKB():
- Enter, only when the on-screen keyboard's plain grid state is active (no
placeholder/accent popup, not in cursor-mode), becomes a new KEY_KB_ENTER
sentinel meaning "submit the field" -- reusing plain KEY_ENTER there would
insert a stray character, since a CardKB typist's row/col never reflect an
intentional grid selection. Everywhere else Enter is untouched, so
selecting a placeholder or committing an accent still works normally.
- Tab (otherwise unused) becomes KEY_CONTEXT_MENU, standing in for the
"Hold-Enter" long-press gesture CardKB has no way to produce -- without it,
~30 context menus across the UI (message reply/navigate, Bot/Admin/
Repeater, ...) would be unreachable from the keyboard alone.
KeyboardWidget gains a direct-typing path: printable ASCII inserts straight
at the cursor bypassing the grid, Backspace deletes, KEY_KB_ENTER submits.
Build-verified: WioTrackerL1_companion_solo_dual and
WioTrackerL1Eink_companion_solo_dual both compile and link clean; also
smoke-tested Heltec_mesh_solar_companion_radio_ble (no ENV_PIN_SDA/SCL) to
confirm zero regression on boards without the feature.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The bot outgrew "auto-reply" once it gained Actions (!buzz/!gps/!advert/
!gpio1-4) that control device hardware remotely, not just answer messages.
Renames the Tools screen entry and all doc cross-references; already-shipped
release notes (v1.23) are left as-is to match what actually shipped under
that name.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The room server never supported RX boosted gain, while the repeater
does. Three consequences on SX1262/SX1268 boards:
- boosted gain was never applied to the radio at boot, so a room server
ran in power-saving RX mode while an identical repeater ran boosted -
a real receive-sensitivity difference with nothing pointing at it
- _prefs.rx_boosted_gain was never initialised (the prefs are memset to
0 before defaults are set), so it defaulted to off
- 'set radio.rxgain on' replied "Error: unsupported" but CommonCLI had
already written the value to prefs and saved them, so a stale setting
survived reboot and was never applied
Mirror the repeater's implementation: initialise the pref default under
the same USE_SX1262/USE_SX1268 and SX126X_RX_BOOSTED_GAIN guards, apply
it during radio init, and override setRxBoostedGain() so the CLI reports
success and takes effect.
Built Heltec_v3_room_server (SX1262) and LilyGo_T3S3_sx1276_room_server
(guards compile out cleanly).
- Auto-Reply Bot gains Actions (!buzz/!gps/!advert) behind a new per-target
toggle nested under Commands (bot_actions_dm/ch/room); off by default.
- Bot Trigger fields accept comma-separated multiple phrases, matching any
one fires the reply.
- New user-assignable GPIO feature (Wio Tracker L1): !gpio1..!gpio4 bot
commands plus a Tools > GPIO screen. Each pin cycles Off/Input/Output;
GPIO1/GPIO2 (P0.02/P0.29, the nRF52840's AIN0/AIN5) also offer a read-only
Analog mode via direct SAADC access. GPIO3/GPIO4 (P0.09/P0.10) are the
chip's NFC1/NFC2 pins, repurposed as plain GPIO via a one-time UICR
NFCPINS bit-clear in initVariant() (adapted from Adafruit's own
nfc_to_gpio example) -- confirmed working on real hardware.
- Fix: DM/room reply-prefix ("@[nick] ") stripping happened at the wrong
layer, hiding the "To:" header on DM replies and leaking the raw prefix
into room messages' list view; a related mismatch had the history
scrollbar's sizing pass wrap room messages with the sender name still
attached, disagreeing with the actual rendered text.
Build-verified: WioTrackerL1_companion_solo_dual and
WioTrackerL1Eink_companion_solo_dual both compile and link clean
(sizeof(NodePrefs) confirmed 2720 via real build, not guessed).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Compile fails due to user_btn not declared in board target.
Fixes:
- Add MomentaryButton declaration for user_btn in variants/xiao_nrf52/target.cpp
- Add momentary button helper include in variants/xiao_nrf52/target.h
- Add extern linkage for MomentaryButton -> user_btn in variants/xiao_nrf52/target.h
SerialEthernetInterface.cpp is compiled for every nRF52 target because
PlatformIO builds all .cpp files under src/. It includes
SerialEthernetInterface.h, which unconditionally pulls in
<RAK13800_W5100S.h> -- a library only present in the RAK4631 Ethernet
env's lib_deps. As a result any other nRF52 board (e.g. Heltec T114)
fails to build with 'RAK13800_W5100S.h: No such file or directory'.
Wrap the contents of both files in '#ifdef ETHERNET_ENABLED' so they
compile to empty translation units on non-Ethernet builds. RAK4631
Ethernet envs define ETHERNET_ENABLED and are unaffected.
Fixes#2985
Improvements:
- Add condition to only turn off display if on (avoids wedging the shutdown on some displays)
- Reset LoRa radio before calling radio_driver.powerOff() to ensure it is in a known good state (and will accept the command)
- Ensure SPI is started so LoRa radio commands can be sent (some shutdowns can happen before this)
- Add gate for P_LORA_NSS pin defined before writing to the pin
setTxTimeoutMs() and setTxBufferSize() are HWCDC-only APIs; calling
them on HardwareSerial (UART-bridge boards like T-Beam) fails to compile.
Co-Authored-By: Adam Gessaman <adam@gessaman.com>
The new test_kiss_modem suite needs KissModem headers and sources that
only native_kiss_modem provides. Scope native to test_utils and run both
envs in the unit test workflow.
Switch ESP32-S3 KISS modem environments to HWCDC and move outbound KISS writes to a non-blocking queued frame path so loop() and TX completion keep progressing when the host reads slowly. Add native backpressure regression tests and correct the native_kiss_modem test filter so this suite runs directly with pio test.
"+ Add channel" jumped straight into a generic Name+Secret form, so the
"hashtag channel" convention documented in docs/companion_protocol.md
(secret = first 16 bytes of sha256("#topic")) was only reachable by
already knowing to type a literal "#topic" into the passphrase field --
nothing in the UI surfaced it. The phone app instead shows an explicit
channel-type picker; this adds the same on-device.
"+ Add channel" now asks Public / Hashtag / Private first:
- Public commits immediately with the well-known default channel's name
and secret (8b3387e9c5cdea6ac9e5edbaa115cd72, confirmed to match
MyMesh.cpp's PUBLIC_GROUP_PSK and the docs' published key) -- useful
to restore it if deleted.
- Hashtag shows a single Topic field; Save synthesizes name="#topic" and
derives the secret via the existing SHA-256 passphrase path -- same
underlying mechanism Private already had, just discoverable without
knowing the "#" convention.
- Private is today's manual Name+Secret form, unchanged.
Editing an existing channel skips the picker (no ambiguity to resolve
there). Extracted hexToSecret() out of deriveSecret()'s hex-mode branch
so Public's fixed key parses through the same code instead of a second
hand-rolled loop. No other file needed changes -- openAdd()/openEdit()/
active()/render()/handleInput() keep their existing signatures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
UITask::newMsg() (fired for every incoming DM/channel message) triggers a
3s "Msg: <sender>" overlay drawn on top of whatever screen is current --
including the shared KeyboardWidget when it's occupying the full screen
for text entry (message compose, room/repeater password, channel name,
device name, admin custom command, ...). A message arriving mid-typing
blanked out the letter grid for the full 3s with no way to see what was
being typed.
KeyboardWidget now tracks whether it was actually rendered this frame
(_visible, set at the top of render(), cleared by the new beginFrame()).
UITask's render loop calls _kb.beginFrame() before curr->render() and
skips the alert overlay when the keyboard turned out to be what got
drawn -- covers every screen that shares _kb, not just message compose.
The alert itself is unaffected (still fires, still expires after 3s) --
it just doesn't draw over the keyboard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>