From a90a01f2aad9553d0d981441613eb68469038153 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 5 Jul 2026 00:10:31 -0700 Subject: [PATCH] fix(lf): correct T55xx write/wakeup structs, 2-byte LF tune, fire-and-forget sampling config lf.tune sends the 2-byte {mode,divisor} the firmware requires (was 3 -> EINVARG/0V). t55.writebl packs the 10-byte {data,pwd,blockno,flags} struct with a single bit-packed flags byte (was 12). t55.wakeup packs 5 bytes {pwd,flags}. t55.config is maintained client-side (firmware has no GET). LF_SAMPLING_SET_CONFIG uses send_ng_no_response (firmware never replies). Pre-existing, independent of the rebase. --- pm3py/core/lf.py | 66 ++++++++++++++++++++++++++++++------------------ tests/test_lf.py | 55 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 26 deletions(-) diff --git a/pm3py/core/lf.py b/pm3py/core/lf.py index f75de22..f1c171b 100644 --- a/pm3py/core/lf.py +++ b/pm3py/core/lf.py @@ -28,32 +28,49 @@ class T55xxCommands: password: int | None = None, downlink_mode: int = 0) -> dict: """Write a T55xx block.""" pwd = password if password is not None else 0 - pwd_mode = 1 if password is not None else 0 - payload = struct.pack(" dict: + async def wakeup(self, password: int = 0, downlink_mode: int = 0) -> dict: """Wake up T55xx with password.""" - payload = struct.pack(" dict: - """Get T55xx timing configuration.""" - resp = await self._t.send_ng(Cmd.LF_T55XX_SET_CONFIG) - # Response is t55xx_configurations_t: 4 modes x 7 uint16_t each - modes = [] - for i in range(4): - offset = i * 14 - if offset + 14 <= len(resp.data): - fields = struct.unpack_from("= 4 else 0 @@ -155,8 +172,9 @@ class LFCommands: trigger_threshold if trigger_threshold is not None else current.get("trigger_threshold", 0), samples_to_skip if samples_to_skip is not None else current.get("samples_to_skip", 0), 0) - resp = await self._t.send_ng(Cmd.LF_SAMPLING_SET_CONFIG, payload) - return {"status": resp.status, **await self.config()} + # Firmware never replies to LF_SAMPLING_SET_CONFIG — fire-and-forget + await self._t.send_ng_no_response(Cmd.LF_SAMPLING_SET_CONFIG, payload) + return {"status": 0, **await self.config()} async def download_samples(self, start: int = 0, count: int = 30000, on_progress: ProgressCallback = None) -> bytes: diff --git a/tests/test_lf.py b/tests/test_lf.py index 0579d86..bddd9ae 100644 --- a/tests/test_lf.py +++ b/tests/test_lf.py @@ -11,11 +11,15 @@ def make_response(cmd, status, data): def test_lf_tune(): t = AsyncMock() lf = LFCommands(t) - # First call: init, second call: poll returns data + # First call: init, second call: measure returns uint32 voltage t.send_ng.return_value = make_response(Cmd.MEASURE_ANTENNA_TUNING_LF, 0, struct.pack("