feat(rawcli): complete the 15693 request-flags byte in iso15_frame

The header builder previously set only high-rate, inventory+1slot, addressed and
option — F15_PROTO_EXT and F15_SELECT were even defined but unused, so several valid
request-flag bits could not be expressed. Complete it: sub-carrier (0x01), protocol-
extension (0x08), Select (0x10), 16-slot inventory (Nb_slots=0), and the inventory AFI
flag (0x10) with its AFI byte inserted before the params. Bits 5-6 are now branched
correctly by mode (Select/Address for non-inventory, AFI/Nb_slots for inventory), per
ISO 15693-3 §7.3.1. iso15_flags_decode decodes every bit in both modes, and the byte-0
flag landmarks gain select (0x12) and inventory+AFI (0x36).

Existing frames are unchanged (verified by the preserved 0x02/0x22/0x42/0x26 tests);
adds coverage for every newly-settable bit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-16 13:01:54 -07:00
parent 7b028f4ddc
commit 251e276fbb
3 changed files with 73 additions and 22 deletions

View File

@@ -438,12 +438,27 @@ class TestCatalog:
f = iso15_frame(0x20, bytes([4]), uid="e004010203040506", addressed=True)
assert f == bytes.fromhex("2220") + bytes.fromhex("e004010203040506")[::-1] + bytes([4])
assert iso15_frame(0x20, bytes([4]), option=True) == b"\x42\x20\x04"
# full flags coverage: every request-flag bit is settable
assert iso15_frame(0x20, bytes([4]), select=True) == b"\x12\x20\x04" # 0x10 select
assert iso15_frame(0x20, bytes([4]), proto_ext=True) == b"\x0A\x20\x04" # 0x08 proto-ext
assert iso15_frame(0x20, bytes([4]), two_subcarrier=True) == b"\x03\x20\x04" # 0x01
assert iso15_frame(0x20, bytes([4]), high_rate=False) == b"\x00\x20\x04" # low rate
assert iso15_frame(0x01, inventory=True, slots16=True) == b"\x06\x01" # 16-slot inventory
# inventory AFI: flag 0x10 set + AFI byte inserted before the params (mask/blocks)
assert iso15_frame(0x01, bytes([0]), inventory=True, afi=0x9A) == bytes.fromhex("36019a00")
def test_iso15_flags_decode(self):
assert iso15_flags_decode(0x02) == "high rate · non-addressed"
assert iso15_flags_decode(0x22) == "high rate · addressed"
assert "option" in iso15_flags_decode(0x42)
assert "inventory" in iso15_flags_decode(0x26)
# every bit decodes, in both modes
assert "select" in iso15_flags_decode(0x12)
assert "protocol-ext" in iso15_flags_decode(0x0A)
assert "two subcarrier" in iso15_flags_decode(0x03)
assert "16 slots" in iso15_flags_decode(0x06)
assert "AFI" in iso15_flags_decode(0x36)
assert iso15_flags_decode(0x00).startswith("low rate")
def test_slix_catalog(self):
# ICODE SLIX datasheet command set: standard + NXP custom, frames via the header builder