feat(registers): NTAG5 STATUS_REG / CONFIG_REG self-describing views
Add Ntag5StatusReg and Ntag5ConfigReg (Register subclasses) and bind them as tag.status_reg / tag.config_reg on the NTAG 5 platform. Purely additive: every existing per-field accessor (disable_nfc, arbiter_mode, sram_enable, ...) stays, and the config_reg setter re-syncs the _arbiter_mode / _sram_enabled sibling caches the per-field setters keep, so the sim internals are untouched. - Ntag5StatusReg (0xA0): field/VCC/boot/lock/EEPROM/SRAM status bits - Ntag5ConfigReg (0xA1): disable_nfc, arbiter_mode (normal/mirror/ pass-through/PHDC), sram_enable, config_pt_transfer_dir Bit layout taken straight from the existing hand-rolled accessors, so the register view decodes the very same bytes (cross-checked in tests). 5 new tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ from pm3py.sim import (
|
||||
MifareAccessConditions, MifareClassicTag,
|
||||
EM4100Code, EM4100Tag,
|
||||
NtagI2CConfig, NtagI2CSession, NtagI2CPtI2C, NT3H2111, NT3H2211,
|
||||
Ntag5StatusReg, Ntag5ConfigReg, Ntag5LinkTag,
|
||||
)
|
||||
|
||||
|
||||
@@ -375,3 +376,58 @@ class TestNtagI2CRegisters:
|
||||
assert "NTAG I2C config registers" in text
|
||||
assert "transfer_dir" in text and "NFC->I2C" in text
|
||||
assert "sram_mirror_block" in text
|
||||
|
||||
|
||||
class TestNtag5Registers:
|
||||
def test_config_reg_field_positions(self):
|
||||
cfg = Ntag5ConfigReg(0)
|
||||
cfg.arbiter_mode = "pass-through" # 0b10 at byte0 bits 3:2
|
||||
cfg.sram_enable = True # byte0 bit1
|
||||
cfg.disable_nfc = True # byte0 bit5
|
||||
cfg.config_pt_transfer_dir = "NFC->I2C" # byte0 bit0
|
||||
# byte0 = 0b0010_1011 = 0x2B (disable_nfc bit5 + arb=10 at bit3 + sram bit1 + ptdir bit0)
|
||||
assert bytes(cfg)[0] == 0x2B
|
||||
assert cfg.arbiter_mode == "pass-through"
|
||||
assert cfg.disable_nfc is True
|
||||
|
||||
def test_status_reg_decode(self):
|
||||
# byte0: nfc_field_ok(0)+vcc_supply_ok(1)+eeprom_wr_busy(7); byte1: nfc_if_locked(0)
|
||||
st = Ntag5StatusReg(int.from_bytes(bytes([0b1000_0011, 0x01, 0, 0]), "big"))
|
||||
assert st.nfc_field_ok is True
|
||||
assert st.vcc_supply_ok is True
|
||||
assert st.eeprom_wr_busy is True
|
||||
assert st.sram_data_ready is False
|
||||
assert st.nfc_if_locked is True
|
||||
|
||||
def test_view_agrees_with_existing_accessors(self):
|
||||
tag = Ntag5LinkTag()
|
||||
tag.arbiter_mode = 2 # existing per-field setter
|
||||
tag.disable_nfc = True
|
||||
tag.sram_enable = True
|
||||
# the register view must decode the very same bytes
|
||||
assert tag.config_reg.arbiter_mode == "pass-through"
|
||||
assert tag.config_reg.disable_nfc is True
|
||||
assert tag.config_reg.sram_enable is True
|
||||
|
||||
def test_assign_config_reg_updates_accessors_and_siblings(self):
|
||||
tag = Ntag5LinkTag()
|
||||
cfg = Ntag5ConfigReg(0)
|
||||
cfg.arbiter_mode = "mirror" # 1
|
||||
cfg.sram_enable = True
|
||||
tag.config_reg = cfg
|
||||
# existing property accessors (read straight off the bytes) must reflect it
|
||||
assert tag.arbiter_mode == 1
|
||||
assert tag.sram_enable is True
|
||||
# and the sibling caches the individual setters maintain stay in sync
|
||||
if hasattr(tag, "_arbiter_mode"):
|
||||
assert tag._arbiter_mode == 1
|
||||
if hasattr(tag, "_sram_enabled"):
|
||||
assert tag._sram_enabled is True
|
||||
|
||||
def test_status_reg_binding_roundtrip(self):
|
||||
tag = Ntag5LinkTag()
|
||||
st = tag.status_reg
|
||||
st.i2c_if_locked = True
|
||||
tag.status_reg = st
|
||||
assert tag.i2c_if_locked is True
|
||||
assert tag.status_reg.i2c_if_locked is True
|
||||
|
||||
Reference in New Issue
Block a user