A second SetFemState sent while the first was held for a TX got an
immediate TxBusy, which reached the host before the first request's
reply. With no request IDs, the host could not tell which Set failed.
FEM requests now go through a small ordered queue (Set, Get and their
error replies). Sets still wait for TxDone to be queued and apply
once. Each reply is kept until it can be queued. Capability checks
happen in order at processing time. Only an overflow (more than 4
waiting) replies TxBusy immediately.
Boards own their FEM control through handleCommand() ("get/set
radio.fem.rxgain|txgain"). Use that instead of a parallel set of FEM
virtuals on MainBoard, so any board that implements the commands works
in KISS with no extra code.
- Remove the six FEM virtuals from MainBoard and the board overrides.
- KissModem talks to the board in one adapter. A gain counts as
controllable only if "get" replies exactly "> on" or "> off". "set"
is checked by reading the state back, never by its reply wording.
- SetFemState always replies with the read-back state once the
requested bits pass the capability check.
- Guard the boards' prefs writes against a NULL store. KISS attaches
no prefs, so "set radio.fem.*" would dereference NULL.
- Wio Tracker L1 1W TX gain is exposed again, matching its CLI.
Add SetRxBoostedGain (0x20) / GetRxBoostedGain (0x21, reply 0xA1) and
capability bit 3, the KISS equivalent of the radio.rxgain CLI setting.
It is separate from FEM RX gain; a board may support either or both.
- Support is declared by the driver via a new
RadioLibWrapper::supportsRxBoostedGain() (SX1262, SX1268, LLCC68,
LR1110, LR1121, LR2021), so nothing is written to the radio at boot.
- The set is refused with TxBusy during TX or while host output is
backed up. Otherwise any completed RX packet is delivered first,
because some drivers (LR2021) drop to standby to apply the gain.
- The reply always carries the state read back from the radio.
Driver fixes found along the way, which also affect the radio.rxgain
CLI in regular firmware:
- CustomLR2021 never updated its cached gain state, so the getter
always reported off. It now tracks the applied level per RX path
and rolls RadioLib's cached level back if a write fails.
- CustomLR1110/LR1121 cached the requested state even when the write
failed.
- lr11x0ResetAGC only reapplied the gain when RX_BOOSTED_GAIN was
defined, so a runtime setting was lost on the next AGC reset.
- Wio Tracker L1 1W no longer advertises TX gain control: its setter
drives LORA_PWR_EN, the shared LDO for the SX1262 and the PA, so
"gain off" would power down the radio.
- A SetFemState that arrives mid-TX is now applied after TxDone is
queued, so its reply follows TxDone.
- SetFemState replies (immediate or deferred) are retained until they
fit in the host output queue instead of being dropped, so a change
that took effect is always acknowledged.
- GetFemState replies queue behind an outstanding SetFemState reply;
a further SetFemState returns TxBusy until it clears.
Add SetHardware sub-commands so a host can probe and configure
per-board RF front-end settings:
- GetCapabilities (0x1B): uint32 feature bits (AGC, FEM RX, FEM TX)
- Set/GetAgcResetInterval (0x1C/0x1D): 0-1020 s, 4 s resolution,
0 disables; default stays 30 s
- Set/GetFemState (0x1E/0x1F): apply/value masks for FEM RX (LNA)
and TX (PA) gain; all-or-nothing, Unsupported (0x08) if any
requested bit is not controllable on this board
The AGC scheduler moves from main.cpp into KissModem so it is
configurable and unit-tested. FEM changes that arrive mid-TX are
deferred until the packet ends, since board setters drive FEM pins
directly.
MainBoard gains virtual FEM hooks (canControl/set/is for LNA and PA
gain). Boards that already implemented these methods privately now
expose them as overrides: Heltec V4, V4 R8, T096, Tracker V2,
Station G3 and Wio Tracker L1 1W.
KISS_FIRMWARE_VERSION bumped to 2.
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
```
Payloads of 166 or 167 bytes previously passed the frame-sized bound
(MAX_CHANNEL_DATA_LENGTH = 167) but were rejected by sendGroupData
against MAX_GROUP_DATA_LENGTH (165), causing ERR_CODE_TABLE_FULL (retry
later) to be returned instead of ERR_CODE_ILLEGAL_ARG.
Fixes#3345
- scope the serial config CLI to RP2040; it was exposing the rescue CLI
(cat/rm/erase) on every ESP32 WiFi build, which gates it behind a
physical long-press
- bound and space out RP2040 rejoins: the core's join busy-waits, so cap
it at 5s and retry every 30s instead of every 10s
- stamp the reconnect timer in setup(), so the first loop() doesn't tear
down an association that is still finishing DHCP
- treat stored credentials as a pair, and pass NULL (not "") for an open
network
- teach build_as_lib.py where SerialWifiInterface moved
arduino-pico's WiFi.begin() blocks for up to 2x its 15s timeout, which
stalled the mesh loop on every reconnect attempt; use beginNoBlock().
Log the IP when the link comes up, and the status code when retrying.