From 4e29d11810eed5433e6df6fbbe83a790cf7a3812 Mon Sep 17 00:00:00 2001 From: MCKero Date: Fri, 28 Aug 2026 16:46:55 +0100 Subject: [PATCH] Update the docs now that the BK4819 is modelled The "what this cannot do" section said the transceiver was not modelled and treated that as permanent. Half of it is now wrong: the register interface works. The other half is still true and worth keeping sharp -- analogue behaviour is out of reach because the chip has no public datasheet, so the driver is the only specification and it can only say which registers were written. Rewritten to separate the two: what is modelled and what it fixed (RSSI was hard zero at 18 call sites), the two constraints the untimed spin loops impose, and then the line that does not move. Explicitly warns against reading the new test as evidence about RF. Also corrects the GPIO comment about idling PB9 low. It described the pin as a workaround pending a device model; that model now exists, and the idle level only covers the window between reset and the bus being wired. --- AGENTS.md | 38 +++++++++++++++++++++++++++++--------- README.md | 5 ++++- qemu/py32f071.c | 9 +++++---- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9deb70d..9f676c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -437,17 +437,37 @@ Note the ELF at `uvk5-sat/build/CW/nr7y.cw.elf` carries no DWARF, so gdb reports `'gEeprom' has unknown type`. Scalars work if you cast through their address (`*(unsigned short*)&gDebounceCounter`); struct fields need manual offsets. -## What this cannot do +## The BK4819, and where modelling it stops -It reproduces what the firmware *commanded* — frequency, power step, carrier -keying in time. It does not reproduce the analogue result: keying envelopes, -spurious emissions, sensitivity. +The register interface is modelled (`TYPE_UVK5_BK4819`): the bit-banged three-wire +bus is decoded, registers read back what the firmware wrote, and the ones it reads +without writing return plausible values. Wiring is CS on PF9, SCL PB8, SDA PB9 with +both directions connected. `tools/test_bk4819.py` inspects the register file over QOM. -That is not a gap to close later. The BK4819/BK4829 transceiver has no public -datasheet, so its driver is the only specification available, and a driver tells -you which registers were written, never what left the antenna. Those questions -need a real radio and a spectrum analyser. Do not let anyone conclude otherwise -from a passing emulator test. +This is what it fixed: RSSI used to read hard zero at 18 call sites — -160 dBm — so +the S-meter showed empty and squelch and scan logic evaluated a dead band. The main +screen now comes up on 400 MHz rather than the 18 MHz floor, because band setup is no +longer reading zeros. + +Two constraints are not negotiable, both from untimed spin loops in the firmware: + +- **REG_0C bit 0 must stay clear.** `app/app.c:910` and `:1417` are + `while (BK4819_ReadRegister(BK4819_REG_0C) & 1u)` with no timeout at all. A stuck + bit hangs the guest; it does not degrade. +- **A soft reset must re-seed the measurement registers.** `REG_00` bit 15, which + `BK4819_Init` issues first, would otherwise leave them zero — real hardware keeps + measuring. Not hypothetical: the first test run decoded 48 registers correctly and + still reported RSSI as 0 for precisely this reason. + +**Where it stops.** This models the register interface, not the radio. It reproduces +what the firmware *commanded* — frequency, power step, carrier keying in time — never +the analogue result: keying envelopes, spurious emissions, sensitivity. + +That is not a gap to close later. The chip has no public datasheet, so its driver is +the only specification available, and a driver tells you which registers were +written, never what left the antenna. Those questions need a real radio and a +spectrum analyser. Do not let anyone conclude otherwise from a passing emulator test, +including the one added here. Timing is also deliberately wrong — see the SysTick section in README.md. Fine for menus and control flow; useless for signal timing. diff --git a/README.md b/README.md index a9d62f5..59eb78d 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ has no public datasheet, so its driver is the only specification available. | Keypad and menu navigation | works, including waking from power save | | Serial output (firmware log) | works, appears in the web UI log | | Serial input, CPS programming protocol | works, `-serial` any chardev | +| BK4819 register interface | works, RSSI and status readable | | Timing accuracy | deliberately wrong, see [Timing](#timing) | -| Radio/RF behaviour | not modelled | +| Analogue RF behaviour | **not modelled and never will be**, see [AGENTS.md](AGENTS.md#the-bk4819-and-where-modelling-it-stops) | A short `tools/key.py MENU` opens the menu, UP/DOWN move through it, MENU enters a submenu, and typing a menu number jumps straight to that entry. Press duration @@ -78,6 +79,7 @@ keypresses silently stop working. Run the test after touching that code; test_flash_persist.py flash writes survive a power cycle test_freq_entry.py a typed frequency takes effect and persists test_serial_rx.py the firmware answers programming commands + test_bk4819.py BK4819 register interface, RSSI not stuck at zero lib_kill_emulator.sh cleanup that only ever kills emulators webui.py web remote control: live LCD plus clickable keypad dn42_firewall.sh restrict the web UI port to DN42 sources @@ -121,6 +123,7 @@ Then check the build actually works, which takes about a minute: python3 tools/test_flash_persist.py python3 tools/test_freq_entry.py python3 tools/test_serial_rx.py + python3 tools/test_bk4819.py This matters more than it looks. The keypad can break silently under -O2 without any compiler warning -- see the `volatile` note in [Status](#status) -- so a clean diff --git a/qemu/py32f071.c b/qemu/py32f071.c index 2917033..c409665 100644 --- a/qemu/py32f071.c +++ b/qemu/py32f071.c @@ -341,10 +341,11 @@ static void py32_gpio_reset(DeviceState *dev) * active low, so a floating pin has to read as "not pressed". * * Exception: PB9 is the bidirectional data line of the software-driven - * three-wire bus to the BK4819 transceiver. Idling it high makes every - * register read return 0xFFFF, and RADIO_SetupRegisters then spins forever - * waiting for bit 0 of REG_0C to clear. Idle it low until that bus has a - * device model, so reads come back as zero and the wait terminates. + * three-wire bus to the BK4819 transceiver, which now has a device model + * driving it (see TYPE_UVK5_BK4819). Idle it low anyway, for the window + * between reset and the bus being wired up: a high idle makes reads return + * 0xFFFF, and RADIO_SetupRegisters spins on bit 0 of REG_0C with no timeout, + * so it would hang outright rather than degrade. */ s->idr = 0xffff; if (s->port_name && s->port_name[0] == 'b') {