Every emulated node reads its channel level as 0 dBm — the loudest value an
SX126x can report. Native nodes read it correctly. One line.
Where
variants/host/VirtualSX1262.cpp, returnsData():
static bool returnsData(uint8_t op) {
switch (op) {
case kReadBuffer:
case kReadRegister:
case kGetIrqStatus:
case kGetRxBufferStatus:
case kGetPacketStatus:
case kGetStatus:
case kGetDeviceErrors:
case kGetPacketType:
return true;
kGetRssiInst (0x15) is not in the list.
Why it only bites the emulators
transferByte() takes the padded-command path only when returnsData()
agrees; otherwise it falls through to
return i == 1 ? 0x22 : 0x00;
so byte 1 is the status and every later byte is zero. A native node reaches
runCommand through the framed path, where case kGetRssiInst: fills in[2]
from rssi_ correctly. QEMU and Renode both clock bytes one at a time through
kXfer, so both get the zero.
rssi_ even defaults to a sensible -100, which is why this is invisible from
the outside: the value is right and never reaches the wire.
Measured
Renode, Heltec_t114, watching opcode 0x15 in both directions:
before 0x15 -> chip said: 22 00 RssiInst 0x00 = 0 dBm
after 0x15 -> chip said: 22 C8 RssiInst 0xC8 = -100 dBm
RSSI(dBm) = -RssiInst / 2, so 0x00 is 0 dBm and 0xC8 is -100 dBm. The
firmware polls this thousands of times a run.
The fix
case kGetPacketStatus:
case kGetRssiInst:
case kGetStatus:
Built and run against a real board from a scratch copy; nothing in this
repository was modified.
What it does not fix
It does not make emulated boards relay. With it applied the board's behaviour is
byte-identical — SetSleep 1,998 times, SetRx 39, IRQ flags never set, no
relay — so whatever stops those boards is something else. Filed on its own
merits: anything consulting the channel level under emulation is currently
working from the loudest reading the part can give.
Context and the rest of that investigation: MeshBench/meshbench#136.
Every emulated node reads its channel level as 0 dBm — the loudest value an
SX126x can report. Native nodes read it correctly. One line.
Where
variants/host/VirtualSX1262.cpp,returnsData():kGetRssiInst(0x15) is not in the list.Why it only bites the emulators
transferByte()takes the padded-command path only whenreturnsData()agrees; otherwise it falls through to
so byte 1 is the status and every later byte is zero. A native node reaches
runCommandthrough the framed path, wherecase kGetRssiInst:fillsin[2]from
rssi_correctly. QEMU and Renode both clock bytes one at a time throughkXfer, so both get the zero.rssi_even defaults to a sensible-100, which is why this is invisible fromthe outside: the value is right and never reaches the wire.
Measured
Renode,
Heltec_t114, watching opcode 0x15 in both directions:RSSI(dBm) = -RssiInst / 2, so0x00is 0 dBm and0xC8is -100 dBm. Thefirmware polls this thousands of times a run.
The fix
Built and run against a real board from a scratch copy; nothing in this
repository was modified.
What it does not fix
It does not make emulated boards relay. With it applied the board's behaviour is
byte-identical —
SetSleep1,998 times,SetRx39, IRQ flags never set, norelay — so whatever stops those boards is something else. Filed on its own
merits: anything consulting the channel level under emulation is currently
working from the loudest reading the part can give.
Context and the rest of that investigation: MeshBench/meshbench#136.