fix(hf): tune() must send START/MEASURE/STOP mode byte and parse uint16

CMD_MEASURE_ANTENNA_TUNING_HF requires a 1-byte mode arg (firmware rejects length!=1 with EINVARG) and returns the voltage as uint16, not uint32. tune() sent no arg (empty reply -> 0 mV) and parsed <I. Now sends mode 1/2/3 (START/MEASURE/STOP) and parses <H. Verified vs firmware appmain.c handler; C client reads the same ~15V on this firmware.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-04 22:38:23 -07:00
parent 687c92a7f7
commit 35f16b7664
2 changed files with 18 additions and 5 deletions

View File

@@ -16,9 +16,17 @@ class HFCommands:
self.mfc = None # type: ignore
async def tune(self, on_progress: ProgressCallback = None) -> dict:
"""Measure HF antenna voltage."""
resp = await self._t.send_ng(Cmd.MEASURE_ANTENNA_TUNING_HF, timeout=10.0)
voltage = struct.unpack_from("<I", resp.data, 0)[0] if len(resp.data) >= 4 else 0
"""Measure HF antenna voltage.
CMD_MEASURE_ANTENNA_TUNING_HF is a START/MEASURE/STOP state machine that
requires a 1-byte mode arg (firmware rejects length!=1 with EINVARG):
mode 1 = START (spins up the HF FPGA), mode 2 = MEASURE (returns uint16 mV),
mode 3 = STOP. Voltage is a uint16_t, not uint32_t.
"""
await self._t.send_ng(Cmd.MEASURE_ANTENNA_TUNING_HF, bytes([1]), timeout=10.0) # START
resp = await self._t.send_ng(Cmd.MEASURE_ANTENNA_TUNING_HF, bytes([2]), timeout=10.0) # MEASURE
voltage = struct.unpack_from("<H", resp.data, 0)[0] if len(resp.data) >= 2 else 0
await self._t.send_ng(Cmd.MEASURE_ANTENNA_TUNING_HF, bytes([3]), timeout=10.0) # STOP
result = {
"voltage_mV": voltage,
"voltage_V": round(voltage / 1000.0, 3),

View File

@@ -7,7 +7,12 @@ from pm3py.core.hf import HFCommands
def test_hf_tune():
t = AsyncMock()
hf = HFCommands(t)
# MEASURE (mode 2) returns the voltage as a uint16 mV; 15485 mV = 0x3C7D
t.send_ng.return_value = PM3Response(cmd=Cmd.MEASURE_ANTENNA_TUNING_HF, status=0,
reason=0, ng=True, data=b"\x00" * 4)
reason=0, ng=True, data=b"\x7d\x3c")
result = asyncio.get_event_loop().run_until_complete(hf.tune())
assert "voltage_mV" in result
assert result["voltage_mV"] == 15485
assert result["voltage_V"] == 15.485
# Firmware requires the START(1)/MEASURE(2)/STOP(3) mode-byte sequence
modes = [call.args[1] for call in t.send_ng.call_args_list]
assert modes == [bytes([1]), bytes([2]), bytes([3])]