#!/usr/bin/env python3 """ Configure NTAG5Link energy harvesting for 1.8V automatic VOUT. Writes EH_CONFIG to persistent EEPROM (block 0x3D) so the NTAG5 automatically outputs 1.8V when an NFC field is present — powering the SAMD21 MCU without any firmware intervention. Also sets ED_CONFIG (FD pin) for NFC-to-I2C SRAM pass-through so the MCU can detect SRAM writes from the phone. Usage: # Read current EH config: python provision_eh.py --read # Write 1.8V / 6.5mA EH config: python provision_eh.py --write # Write with custom current limit: python provision_eh.py --write --current 4.0 # Also configure CONFIG_0 and CONFIG_1 for xblink: python provision_eh.py --write --full """ import argparse import sys import os # Add ntag5sensor to path ntag5sensor_path = os.path.join(os.path.dirname(__file__), "..", "..", "ntag5sensor") sys.path.insert(0, ntag5sensor_path) from reader.acr1552 import ACR1552 from vicinity.iso15693 import ISO15693 from vicinity.ntag5link import ( Ntag5Link, NXP_EH_CONFIG_EH_VOUT_V_SEL_1_8, NXP_EH_CONFIG_EH_VOUT_V_SEL_2_4, NXP_EH_CONFIG_EH_VOUT_V_SEL_3_0, NXP_EH_CONFIG_EH_VOUT_I_SEL_0_4, NXP_EH_CONFIG_EH_VOUT_I_SEL_0_6, NXP_EH_CONFIG_EH_VOUT_I_SEL_1_4, NXP_EH_CONFIG_EH_VOUT_I_SEL_2_7, NXP_EH_CONFIG_EH_VOUT_I_SEL_4_0, NXP_EH_CONFIG_EH_VOUT_I_SEL_6_5, NXP_EH_CONFIG_EH_VOUT_I_SEL_9_0, NXP_EH_CONFIG_EH_VOUT_I_SEL_12_5, NXP_ED_CONFIG_NFC_TO_I2C_PASS_THROUGH, NXP_CONFIG_0_EH_MODE_LOW_FIELD_STRENGTH, NXP_CONFIG_1_ARBITER_MODE_SRAM_PASSTHROUGH, NXP_CONFIG_1_USE_CASE_CONF_I2C_SLAVE, ) # Current limit lookup: string -> constant CURRENT_MAP = { "0.4": NXP_EH_CONFIG_EH_VOUT_I_SEL_0_4, "0.6": NXP_EH_CONFIG_EH_VOUT_I_SEL_0_6, "1.4": NXP_EH_CONFIG_EH_VOUT_I_SEL_1_4, "2.7": NXP_EH_CONFIG_EH_VOUT_I_SEL_2_7, "4.0": NXP_EH_CONFIG_EH_VOUT_I_SEL_4_0, "6.5": NXP_EH_CONFIG_EH_VOUT_I_SEL_6_5, "9.0": NXP_EH_CONFIG_EH_VOUT_I_SEL_9_0, "12.5": NXP_EH_CONFIG_EH_VOUT_I_SEL_12_5, } def read_config(chip): """Read and display current EH and general config.""" print("=== NTAG5 Configuration ===\n") info = chip.get_system_info() print(f"UID: {info['uid'].hex()}") config = chip.get_config_info() print(f"\nCONFIG_0:") print(f" EH mode: {config.get('energy_harvesting_mode', '?')}") print(f" SRAM copy: {config.get('sram_copy_enabled', '?')}") print(f" Auto standby: {config.get('auto_standby_mode', '?')}") print(f"\nCONFIG_1:") print(f" SRAM enable: {config.get('sram_enabled', '?')}") print(f" Arbiter mode: {config.get('arbiter_mode', '?')}") print(f" Use case: {config.get('use_case', '?')}") print(f" EH arbiter: {config.get('eh_arbiter_mode_enabled', '?')}") eh = chip.get_eh_ed_config_info() print(f"\nEH_CONFIG (block 0x3D):") print(f" EH enable: {eh.get('eh_enable', '?')}") print(f" VOUT voltage: {eh.get('eh_vout_v_sel', '?')}V") print(f" VOUT current: {eh.get('eh_vout_i_sel', '?')}mA") print(f" Power check disabled: {eh.get('disable_power_check', '?')}") print(f" ED/FD config: {eh.get('ed_config', '?')}") def write_eh(chip, current_sel, full_config=False): """Write EH config for 1.8V automatic come-up.""" print("Writing EH config: 1.8V, current limit = " f"{[k for k,v in CURRENT_MAP.items() if v == current_sel][0]}mA") print(f" ED/FD pin: NFC-to-I2C pass-through (SRAM write detect)") chip.write_eh_ed_config( enable=True, disable_power_check=False, current=current_sel, voltage=NXP_EH_CONFIG_EH_VOUT_V_SEL_1_8, ed_config=NXP_ED_CONFIG_NFC_TO_I2C_PASS_THROUGH, ) print(" EH_CONFIG written.") if full_config: print("\nWriting CONFIG_0: EH mode = low field strength") chip.write_config0( eh_mode=NXP_CONFIG_0_EH_MODE_LOW_FIELD_STRENGTH, ) print(" CONFIG_0 written.") print("Writing CONFIG_1: SRAM enable, arbiter=passthrough, use_case=I2C slave") chip.write_config1( sram_enable=True, arbiter_mode=NXP_CONFIG_1_ARBITER_MODE_SRAM_PASSTHROUGH, use_case=NXP_CONFIG_1_USE_CASE_CONF_I2C_SLAVE, ) print(" CONFIG_1 written.") # Verify print("\n--- Verify ---") read_config(chip) def main(): parser = argparse.ArgumentParser( description="Configure NTAG5Link energy harvesting for 1.8V") parser.add_argument("--read", action="store_true", help="Read current config (no writes)") parser.add_argument("--write", action="store_true", help="Write EH config for 1.8V automatic VOUT") parser.add_argument("--current", default="6.5", choices=list(CURRENT_MAP.keys()), help="VOUT current limit in mA (default: 6.5)") parser.add_argument("--full", action="store_true", help="Also write CONFIG_0 and CONFIG_1 for xblink") args = parser.parse_args() if not args.read and not args.write: parser.print_help() sys.exit(1) reader = ACR1552() reader.connect() iso = ISO15693(reader) chip = Ntag5Link(iso) if args.read: read_config(chip) if args.write: current_sel = CURRENT_MAP[args.current] write_eh(chip, current_sel, full_config=args.full) reader.disconnect() if __name__ == "__main__": main()