Skip to content

Commit 0fb5703

Browse files
committed
fix(kiss): periodic noise floor calibration and AGC reset
- Trigger noise floor calibration every 2s and AGC reset every 30s in main loop. - Reorder loop to match Dispatcher: calibrate + radio.loop() before AGC reset and recvRaw() so RSSI is never sampled right after startReceive(). - Update protocol doc with calibration intervals and typical noise floor range. - Variant platformio.ini updates (heltec_v3, rak4631).
1 parent e03f311 commit 0fb5703

4 files changed

Lines changed: 54 additions & 9 deletions

File tree

docs/kiss_modem_protocol.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Maximum unescaped frame size: 512 bytes.
2828

2929
## Commands
3030

31+
Command and response codes below are taken from `examples/kiss_modem/KissModem.h` and the switch in `KissModem::processFrame()`.
32+
3133
### Request Commands (Host → Modem)
3234

3335
| Command | Value | Data |
@@ -43,10 +45,10 @@ Maximum unescaped frame size: 512 bytes.
4345
| `CMD_HASH` | `0x08` | Data to hash |
4446
| `CMD_SET_RADIO` | `0x09` | Freq (4) + BW (4) + SF (1) + CR (1) |
4547
| `CMD_SET_TX_POWER` | `0x0A` | Power dBm (1) |
46-
| `CMD_SET_SYNC_WORD` | `0x0B` | Sync word (1) |
48+
| *reserved* | `0x0B` | *(not implemented)* |
4749
| `CMD_GET_RADIO` | `0x0C` | - |
4850
| `CMD_GET_TX_POWER` | `0x0D` | - |
49-
| `CMD_GET_SYNC_WORD` | `0x0E` | - |
51+
| *reserved* | `0x0E` | *(not implemented)* |
5052
| `CMD_GET_VERSION` | `0x0F` | - |
5153
| `CMD_GET_CURRENT_RSSI` | `0x10` | - |
5254
| `CMD_IS_CHANNEL_BUSY` | `0x11` | - |
@@ -73,7 +75,7 @@ Maximum unescaped frame size: 512 bytes.
7375
| `RESP_OK` | `0x29` | - |
7476
| `RESP_RADIO` | `0x2A` | Freq (4) + BW (4) + SF (1) + CR (1) |
7577
| `RESP_TX_POWER` | `0x2B` | Power dBm (1) |
76-
| `RESP_SYNC_WORD` | `0x2C` | Sync word (1) |
78+
| *reserved* | `0x2C` | *(not implemented)* |
7779
| `RESP_VERSION` | `0x2D` | Version (1) + Reserved (1) |
7880
| `RESP_ERROR` | `0x2E` | Error code (1) |
7981
| `RESP_TX_DONE` | `0x2F` | Result (1): 0x00=failed, 0x01=success |
@@ -119,9 +121,19 @@ All values little-endian.
119121
| RSSI | 1 byte | Signal strength dBm, signed |
120122
| Packet | variable | Raw MeshCore packet |
121123

124+
### Noise Floor (RESP_NOISE_FLOOR)
125+
126+
Response to `CMD_GET_NOISE_FLOOR` (0x13). Little-endian.
127+
128+
| Field | Size | Description |
129+
|--------------|------|--------------------------------|
130+
| Noise floor | 2 | int16_t, dBm (signed), e.g. -120 |
131+
132+
The modem recalibrates the noise floor periodically (every 2 s) from RX samples when idle. The receiver AGC is also reset periodically (every 30 s) so RSSI and noise floor do not drift to the minimum (-120). Typical range after calibration is about -120 to -90 dBm. Values may be 0 or briefly stale until the radio has been in receive mode long enough to collect 64 samples.
133+
122134
### Stats (RESP_STATS)
123135

124-
All values little-endian.
136+
Response to `CMD_GET_STATS` (0x14). All values little-endian.
125137

126138
| Field | Size | Description |
127139
|-------|------|-------------|

examples/kiss_modem/main.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@
1212
#include <SPIFFS.h>
1313
#endif
1414

15+
#define NOISE_FLOOR_CALIB_INTERVAL_MS 2000 // match Dispatcher default
16+
#define AGC_RESET_INTERVAL_MS 30000 // periodic RX restart so AGC doesn't drift (repeater uses same via prefs)
17+
1518
StdRNG rng;
1619
mesh::LocalIdentity identity;
1720
KissModem* modem;
21+
static uint32_t next_noise_floor_calib_ms = 0;
22+
static uint32_t next_agc_reset_ms = 0;
1823

1924
void halt() {
2025
while (1) ;
@@ -94,7 +99,16 @@ void loop() {
9499

95100
uint8_t packet[KISS_MAX_PACKET_SIZE];
96101
uint16_t len;
97-
102+
103+
// Match Dispatcher order: noise floor calib + loop() first, so we never sample RSSI in the same
104+
// iteration as startReceive() (AGC reset -> recvRaw below). Sampling right after startReceive()
105+
// can yield settling/cold RSSI and drive the floor toward -120.
106+
if ((uint32_t)(millis() - next_noise_floor_calib_ms) >= NOISE_FLOOR_CALIB_INTERVAL_MS) {
107+
radio_driver.triggerNoiseFloorCalibrate(0); // 0 = no interference threshold (KISS has no prefs)
108+
next_noise_floor_calib_ms = millis();
109+
}
110+
radio_driver.loop();
111+
98112
if (modem->getPacketToSend(packet, &len)) {
99113
radio_driver.startSendRaw(packet, len);
100114
while (!radio_driver.isSendComplete()) {
@@ -104,14 +118,15 @@ void loop() {
104118
modem->onTxComplete(true);
105119
}
106120

121+
if ((uint32_t)(millis() - next_agc_reset_ms) >= AGC_RESET_INTERVAL_MS) {
122+
radio_driver.resetAGC(); // next recvRaw() will startReceive() and reset AGC so RSSI/noise floor don't stick at -120
123+
next_agc_reset_ms = millis();
124+
}
107125
uint8_t rx_buf[256];
108126
int rx_len = radio_driver.recvRaw(rx_buf, sizeof(rx_buf));
109-
110127
if (rx_len > 0) {
111128
int8_t snr = (int8_t)(radio_driver.getLastSNR() * 4);
112129
int8_t rssi = (int8_t)radio_driver.getLastRSSI();
113130
modem->onPacketReceived(snr, rssi, rx_buf, rx_len);
114131
}
115-
116-
radio_driver.loop();
117132
}

variants/heltec_v3/platformio.ini

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,12 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter}
367367
lib_deps =
368368
${Heltec_lora32_v3.lib_deps}
369369
${esp32_ota.lib_deps}
370+
371+
[env:Heltec_v3_kiss_modem]
372+
extends = Heltec_lora32_v3
373+
build_flags =
374+
${Heltec_lora32_v3.build_flags}
375+
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
376+
+<../examples/kiss_modem/>
377+
lib_deps =
378+
${Heltec_lora32_v3.lib_deps}

variants/rak4631/platformio.ini

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,13 @@ build_flags =
183183
-D MESH_DEBUG=1
184184
build_src_filter = ${rak4631.build_src_filter}
185185
+<helpers/ui/SSD1306Display.cpp>
186-
+<../examples/simple_sensor>
186+
+<../examples/simple_sensor>
187+
188+
[env:RAK_4631_kiss_modem]
189+
extends = rak4631
190+
build_flags =
191+
${rak4631.build_flags}
192+
build_src_filter = ${rak4631.build_src_filter}
193+
+<../examples/kiss_modem/>
194+
lib_deps =
195+
${rak4631.lib_deps}

0 commit comments

Comments
 (0)