1. USB takeover opcode mismatch
ZephyrCompanionUSB.cpp checked payload[0] == 0x03 with a comment
claiming CMD_APP_START, but CMD_APP_START is 0x01 (0x03 is
CMD_SEND_CHANNEL_TXT_MSG). The USB handshake silently dropped the
companion app's first frame on every connection; the app appeared
broken over USB until the user happened to send a channel message.
2. CMD_SET_ADVERT_NAME didn't propagate to BLE adv data
Name changes were persisted to prefs but the advertising payload
and GATT device name kept the old value until reboot. Added
zephcore_ble_update_name() and called it from the handler.
3. No advertising-health watchdog
If bt_le_adv_start() ever failed transiently (HCI timeout,
controller pacing), the device would silently stop advertising
and stay undiscoverable until reboot. Added an adv_running flag
and a 5s watchdog in the companion housekeeping handler that
nudges adv back on if it stops outside a connection. Tracks
Arduino nrf52's equivalent 10s watchdog.
every LBT-retried flood packet loses its priority (fixed)
witching between LBT and non-LBT mode (or any cad.mode change) could silently skip full reconfiguration and leave the radio in the wrong mode (fixed)
Add .gitattributes rules so .c/.h/.cpp/.hpp are always stored as LF
(prevents EOL drift from editors with autocrlf-true defaults), and
renormalize the 30 source files that had drifted to CRLF in the index.
Pure mechanical change — `git diff --ignore-cr-at-eol` is empty.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
stolen from Zephyr main:
1. Issue StopTimerOnPreamble=1 before SetRxDutyCycle so the chip's
timer is not reset on every preamble detect (per §13.1 of the
datasheet). Without this, duty cycle effectively never sleeps in
noisy RF and current draw spikes.
2. On IRQ_RX_TX_TIMEOUT during duty-cycle RX, re-arm via
sx126x_restart_rx() instead of falling through to set_sleep().
The old path silently killed duty cycle after the first preamble
false-positive.
3. On recv_duty_cycle(NULL) cancel, wake the radio before issuing
SetStandby — BUSY stays asserted during the sleep phase and the
standby command was being dropped.
Also adds a dc_timeout_restarts atomic counter incremented on the Fix 2
path, exposed end-to-end: sx126x_ext.h accessors → LoRaRadioBase vtable
→ SX126xRadio override → CommonCLICallbacks → RepeaterMesh. Query via
`get dc.restarts` on the repeater CLI; cleared by `clear stats`. High
values indicate a noisy environment or a too-loose preamble threshold.
(+increase ESP BT stack because future zephyr pin advance will trip that mine)
Three correctness fixes for the SX127x radio adapter on top of
Rastislav's initial sx1276 + patch commits:
1. _loramac_node flag (LoRaRadioBase + SX127xRadio):
Guard the direction-only fast path in configureTx()/configureRx()
so loramac-node always calls both Radio.SetTxConfig() and
Radio.SetRxConfig(). Skipping either leaves TxTimeout=0 in the
library, causing an immediate TX timeout callback, which prevents
the _tx_signal from ever being raised and blocks the TX wait thread
for TX_TIMEOUT_MS (5 s) — a 5-second RX blackout per transmission.
This was the root cause of "boots but no RX".
2. SX127xRadio::resetAGC() override:
The base-class resetAGC() calls startReceive() after hwResetAGC().
During async RX the loramac-node modem mutex is STATE_BUSY, so
lora_recv_async() returns -EBUSY, which sets _in_recv_mode = 0 and
corrupts the receive state machine. Override skips the call
entirely — the loramac-node driver self-manages AGC.
3. BW 62.5 kHz support in loramac-node/sx1276.c + patch:
Rastislav's 0004-lora-sx127x-62k5-bandwidth.patch adds BW_62_KHZ
support to sx12xx_common.c (Zephyr side) but not to the loramac-
node library itself. Without this fix bandwidth index 3 hits the
"while(1)" fatal guard in SX1276SetRxConfig/SX1276SetTxConfig.
This commit patches sx1276.c directly and adds
patches/modules/loramac-node/0001-sx1276-bw62k5.patch so the fix
survives west update. CMakeLists.txt is extended to apply module
patches via the existing zephcore_apply_patches() mechanism.
GPS fixes no longer overwrite prefs lat/lon — adverts use only
manually-set coordinates (via gps setloc or companion app)
Precise GPS position served via telemetry requests only
getNodeLat()/getNodeLon() returns live GPS fix
Last good fix persisted to /lfs/gps_pos — survives reboots
| Command | Description |
|---------|-------------|
| `gps` | Show GPS status (`on` or `off`) |
| `gps on` | Enable GPS module |
| `gps off` | Disable GPS module |
| `gps setloc` | Update stored latitude/longitude from current GPS fix |
| `gps advert` | Show current location advertising policy |
| `gps advert none` | Do not include location in advertisements |
| `gps advert share` | Include live GPS location in advertisements |
| `gps advert prefs` | Include stored lat/lon from prefs in advertisements |