mirror of
https://github.com/MCKero6423/uv-k5-v3-emulator.git
synced 2026-10-02 03:15:36 +00:00
Correct the docs that said PTT did not exist
Three places claimed there was no PTT line, and one of them named the wrong pin (GPIOC rather than PB10). All now say the same thing: PTT works, but not through the key table, because the firmware reads its own pin instead of scanning it as a matrix key. Documents the transmit bar's two gates -- FUNCTION_TRANSMIT and gSetting_mic_bar, the latter already on because blank flash reads 0xFF -- and why the release path gets more attention than the press: a stuck PTT leaves every later test running against a transmitting radio. Also records the '.key' vs '.key[data-key]' trap for whoever adds the next non-key button.
This commit is contained in:
1 parent
88994b1bd0
commit
a310429eff
5 files changed
+46
-9
No files matched your search
@@ -459,6 +459,29 @@ Two constraints are not negotiable, both from untimed spin loops in the firmware
|
|||||||
measuring. Not hypothetical: the first test run decoded 48 registers correctly and
|
measuring. Not hypothetical: the first test run decoded 48 registers correctly and
|
||||||
still reported RSSI as 0 for precisely this reason.
|
still reported RSSI as 0 for precisely this reason.
|
||||||
|
|
||||||
|
### PTT, and the transmit level bar
|
||||||
|
|
||||||
|
PTT is not a matrix key. `GPIO_IsPttPressed` reads PB10 directly
|
||||||
|
(`driver/gpio.h:31`, active low), so the model gives it its own GPIO line rather than a
|
||||||
|
column/row intersection, exposed as a boolean `ptt` property on the keypad device.
|
||||||
|
|
||||||
|
That is what makes the transmit level bar reachable. `app/app.c:1700` draws it only
|
||||||
|
while `gCurrentFunction == FUNCTION_TRANSMIT` and `gSetting_mic_bar` is set — the
|
||||||
|
latter is `Data[7]` bit 4 at flash `0xA0A8` (`settings.c:423`), and blank flash reads
|
||||||
|
`0xFF`, so it is already on. The level itself comes from `REG_64` via
|
||||||
|
`BK4819_GetVoiceAmplitudeOut`.
|
||||||
|
|
||||||
|
**Treat the release as the important half.** A stuck PTT leaves the emulated radio
|
||||||
|
keyed, and every later test then runs against a transmitting radio. The web UI releases
|
||||||
|
on `pointerleave`, `pointercancel` and `pagehide`; `/api/release-all` clears PTT
|
||||||
|
explicitly, because an empty `press` does not touch it; and the endpoint rejects
|
||||||
|
non-boolean bodies so `{"held": "false"}` cannot key the transmitter by truthiness.
|
||||||
|
`tools/test_ptt.py` asserts the release, not just the press.
|
||||||
|
|
||||||
|
One trap worth knowing if you add another non-key button: the browser wired handlers
|
||||||
|
over `.key`, which matched the PTT button as well, and it has no `data-key` — so it
|
||||||
|
would have sent the key `"undefined"`. Use `.key[data-key]`.
|
||||||
|
|
||||||
### Reads were shifted one bit, and it hid everything else
|
### Reads were shifted one bit, and it hid everything else
|
||||||
|
|
||||||
Fixed in `ad88ee1`, but worth reading because of how long it stayed invisible.
|
Fixed in `ad88ee1`, but worth reading because of how long it stayed invisible.
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ has no public datasheet, so its driver is the only specification available.
|
|||||||
| Serial input, CPS programming protocol | works, `-serial` any chardev |
|
| Serial input, CPS programming protocol | works, `-serial` any chardev |
|
||||||
| BK4819 register interface | works, RSSI and status readable |
|
| BK4819 register interface | works, RSSI and status readable |
|
||||||
| S-meter | works via monitor (SIDE1); reads -53 dBm, S9+40 |
|
| S-meter | works via monitor (SIDE1); reads -53 dBm, S9+40 |
|
||||||
|
| PTT and transmit | works; TX annunciator, timer, and mic level bar |
|
||||||
| Timing accuracy | deliberately wrong, see [Timing](#timing) |
|
| Timing accuracy | deliberately wrong, see [Timing](#timing) |
|
||||||
| Analogue RF behaviour | **not modelled and never will be**, see [AGENTS.md](AGENTS.md#the-bk4819-and-where-modelling-it-stops) |
|
| Analogue RF behaviour | **not modelled and never will be**, see [AGENTS.md](AGENTS.md#the-bk4819-and-where-modelling-it-stops) |
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ keypresses silently stop working. Run the test after touching that code;
|
|||||||
test_bk4819.py BK4819 register interface, RSSI not stuck at zero
|
test_bk4819.py BK4819 register interface, RSSI not stuck at zero
|
||||||
test_bk4819_readback.sh register reads come back bit-aligned
|
test_bk4819_readback.sh register reads come back bit-aligned
|
||||||
test_smeter.py the S-meter reads a signal when monitoring
|
test_smeter.py the S-meter reads a signal when monitoring
|
||||||
|
test_ptt.py PTT keys the radio and releases cleanly
|
||||||
lib_kill_emulator.sh cleanup that only ever kills emulators
|
lib_kill_emulator.sh cleanup that only ever kills emulators
|
||||||
webui.py web remote control: live LCD plus clickable keypad
|
webui.py web remote control: live LCD plus clickable keypad
|
||||||
dn42_firewall.sh restrict the web UI port to DN42 sources
|
dn42_firewall.sh restrict the web UI port to DN42 sources
|
||||||
@@ -129,6 +131,7 @@ Then check the build actually works, which takes about a minute:
|
|||||||
python3 tools/test_bk4819.py
|
python3 tools/test_bk4819.py
|
||||||
bash tools/test_bk4819_readback.sh
|
bash tools/test_bk4819_readback.sh
|
||||||
python3 tools/test_smeter.py
|
python3 tools/test_smeter.py
|
||||||
|
python3 tools/test_ptt.py
|
||||||
|
|
||||||
This matters more than it looks. The keypad can break silently under -O2 without
|
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
|
any compiler warning -- see the `volatile` note in [Status](#status) -- so a clean
|
||||||
@@ -250,8 +253,17 @@ watching the counters rather than by assuming:
|
|||||||
The rules do not survive a reboot. Re-run `apply`, or persist them with
|
The rules do not survive a reboot. Re-run `apply`, or persist them with
|
||||||
`iptables-persistent`.
|
`iptables-persistent`.
|
||||||
|
|
||||||
There is no PTT button: the keypad model has no PTT line, so the `press` property
|
PTT is separate from the keypad grid, because the firmware reads its own pin (PB10)
|
||||||
rejects the name. Unknown keys are rejected with 400 rather than forwarded.
|
rather than scanning it as a matrix key. It has its own button in the UI and its own
|
||||||
|
endpoint, and it is held rather than tapped:
|
||||||
|
|
||||||
|
curl -X POST -H 'Content-Type: application/json' \
|
||||||
|
-d '{"held": true}' http://127.0.0.1:8080/api/ptt
|
||||||
|
|
||||||
|
Anything that ends a session releases it — dragging off the button, closing the tab,
|
||||||
|
or `POST /api/release-all` — so a client going away cannot leave the radio keyed.
|
||||||
|
The `press` property still rejects "PTT" as a key name; unknown keys get a 400 rather
|
||||||
|
than being forwarded.
|
||||||
|
|
||||||
## How the machine is put together
|
## How the machine is put together
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,9 @@ class TestKeys(unittest.TestCase):
|
|||||||
names = set(re.findall(r'"([^"]+)"', block.group(1)))
|
names = set(re.findall(r'"([^"]+)"', block.group(1)))
|
||||||
self.assertEqual(names, set(KEYS))
|
self.assertEqual(names, set(KEYS))
|
||||||
|
|
||||||
def test_ptt_is_not_offered(self):
|
def test_ptt_is_not_offered_as_a_key(self):
|
||||||
# The keypad model has no PTT line; qom-set would error on it.
|
# PTT works, but not through the key table: the firmware reads its own pin, so
|
||||||
|
# it is a separate boolean property. Setting "press" to PTT would error.
|
||||||
self.assertFalse(is_valid("PTT"))
|
self.assertFalse(is_valid("PTT"))
|
||||||
|
|
||||||
def test_normalise_is_case_insensitive_and_strips(self):
|
def test_normalise_is_case_insensitive_and_strips(self):
|
||||||
|
|||||||
+4
-3
@@ -4,9 +4,10 @@
|
|||||||
Mirrors keypad_key_names in qemu/py32f071.c. test_uvk5_keys.py parses that array
|
Mirrors keypad_key_names in qemu/py32f071.c. test_uvk5_keys.py parses that array
|
||||||
out of the model source and fails if the two drift apart.
|
out of the model source and fails if the two drift apart.
|
||||||
|
|
||||||
PTT is absent on purpose: the keypad model has no PTT line -- it is wired
|
PTT is absent on purpose, and still is now that the model supports it: the firmware
|
||||||
separately on GPIOC -- so the "press" property rejects the name. Offering a PTT
|
reads PB10 directly rather than scanning PTT as a matrix key, so it is exposed as its
|
||||||
button would produce a QMP error rather than a transmission.
|
own boolean property and its own endpoint (POST /api/ptt) instead of a name here. The
|
||||||
|
"press" property rejects "PTT".
|
||||||
"""
|
"""
|
||||||
|
|
||||||
KEYS = (
|
KEYS = (
|
||||||
|
|||||||
+2
-2
@@ -471,8 +471,8 @@ def render_index(scale: int) -> str:
|
|||||||
<p class="hint">How long you hold a key is measured here and sent as one
|
<p class="hint">How long you hold a key is measured here and sent as one
|
||||||
number, so the firmware sees exactly the press you made. Hold past 400 ms for a
|
number, so the firmware sees exactly the press you made. Hold past 400 ms for a
|
||||||
long press, which the firmware treats as a separate event and which repeats.
|
long press, which the firmware treats as a separate event and which repeats.
|
||||||
Arrows move, Enter is MENU, Esc is EXIT, digits map straight through. No PTT
|
Arrows move, Enter is MENU, Esc is EXIT, digits map straight through. PTT is held
|
||||||
button -- the keypad model has no PTT line.</p>
|
rather than measured, and releases if you drag off it or close the tab.</p>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
const BINDINGS = {json.dumps(KEY_BINDINGS)};
|
const BINDINGS = {json.dumps(KEY_BINDINGS)};
|
||||||
|
|||||||
Reference in new issue
Block a user