|
@@ -15,38 +15,23 @@ Wiring (from spoolbuddy/README.md):
|
|
|
PN5180 RST -> Pi Pin 18 (GPIO24)
|
|
PN5180 RST -> Pi Pin 18 (GPIO24)
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
|
|
+import os
|
|
|
import sys
|
|
import sys
|
|
|
import time
|
|
import time
|
|
|
|
|
|
|
|
import gpiod
|
|
import gpiod
|
|
|
-import spidev
|
|
|
|
|
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
-# Pin assignments (BCM numbering)
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
-BUSY_PIN = 25 # Pin 22
|
|
|
|
|
-RST_PIN = 24 # Pin 18
|
|
|
|
|
-NSS_PIN = 23 # Pin 16 (manual CS)
|
|
|
|
|
|
|
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "daemon")))
|
|
|
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
-# SPI command instruction codes (NXP PN5180 datasheet Table 5)
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
-CMD_WRITE_REGISTER = 0x00
|
|
|
|
|
-CMD_WRITE_REGISTER_OR_MASK = 0x01
|
|
|
|
|
-CMD_WRITE_REGISTER_AND_MASK = 0x02
|
|
|
|
|
-CMD_READ_REGISTER = 0x04
|
|
|
|
|
-CMD_READ_REGISTER_MULTIPLE = 0x05
|
|
|
|
|
-CMD_WRITE_EEPROM = 0x06
|
|
|
|
|
-CMD_READ_EEPROM = 0x07
|
|
|
|
|
-CMD_SEND_DATA = 0x09
|
|
|
|
|
-CMD_READ_DATA = 0x0A
|
|
|
|
|
-CMD_LOAD_RF_CONFIG = 0x11
|
|
|
|
|
-CMD_RF_ON = 0x16
|
|
|
|
|
-CMD_RF_OFF = 0x17
|
|
|
|
|
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
-# Register addresses (32-bit each)
|
|
|
|
|
-# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
+from pn5180 import ( # noqa: E402
|
|
|
|
|
+ NSS_PIN as DRIVER_NSS_PIN,
|
|
|
|
|
+ PN5180,
|
|
|
|
|
+ RST_PIN as DRIVER_RST_PIN,
|
|
|
|
|
+ SPI_BUS as DRIVER_SPI_BUS,
|
|
|
|
|
+ SPI_DEVICE as DRIVER_SPI_DEVICE,
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
REG_SYSTEM_CONFIG = 0x00
|
|
REG_SYSTEM_CONFIG = 0x00
|
|
|
REG_IRQ_ENABLE = 0x01
|
|
REG_IRQ_ENABLE = 0x01
|
|
|
REG_IRQ_STATUS = 0x02
|
|
REG_IRQ_STATUS = 0x02
|
|
@@ -60,25 +45,9 @@ REG_RX_STATUS = 0x13
|
|
|
REG_CRC_TX_CONFIG = 0x19
|
|
REG_CRC_TX_CONFIG = 0x19
|
|
|
REG_RF_STATUS = 0x1D
|
|
REG_RF_STATUS = 0x1D
|
|
|
REG_SYSTEM_STATUS = 0x24
|
|
REG_SYSTEM_STATUS = 0x24
|
|
|
|
|
+REG_SIGPRO_CONFIG = 0x1A # Signal Processing Configuration
|
|
|
REG_TEMP_CONTROL = 0x25
|
|
REG_TEMP_CONTROL = 0x25
|
|
|
|
|
|
|
|
-REGISTER_NAMES = {
|
|
|
|
|
- REG_SYSTEM_CONFIG: "SYSTEM_CONFIG",
|
|
|
|
|
- REG_IRQ_ENABLE: "IRQ_ENABLE",
|
|
|
|
|
- REG_IRQ_STATUS: "IRQ_STATUS",
|
|
|
|
|
- REG_IRQ_CLEAR: "IRQ_CLEAR",
|
|
|
|
|
- REG_TRANSCEIVE_CONTROL: "TRANSCEIVE_CONTROL",
|
|
|
|
|
- REG_TIMER1_RELOAD: "TIMER1_RELOAD",
|
|
|
|
|
- REG_TIMER1_CONFIG: "TIMER1_CONFIG",
|
|
|
|
|
- REG_RX_WAIT_CONFIG: "RX_WAIT_CONFIG",
|
|
|
|
|
- REG_CRC_RX_CONFIG: "CRC_RX_CONFIG",
|
|
|
|
|
- REG_RX_STATUS: "RX_STATUS",
|
|
|
|
|
- REG_CRC_TX_CONFIG: "CRC_TX_CONFIG",
|
|
|
|
|
- REG_RF_STATUS: "RF_STATUS",
|
|
|
|
|
- REG_SYSTEM_STATUS: "SYSTEM_STATUS",
|
|
|
|
|
- REG_TEMP_CONTROL: "TEMP_CONTROL",
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ---------------------------------------------------------------------------
|
|
|
# EEPROM addresses
|
|
# EEPROM addresses
|
|
|
# ---------------------------------------------------------------------------
|
|
# ---------------------------------------------------------------------------
|
|
@@ -89,224 +58,39 @@ EEPROM_EEPROM_VERSION = 0x14 # 2 bytes
|
|
|
EEPROM_IRQ_PIN_CONFIG = 0x1A # 1 byte
|
|
EEPROM_IRQ_PIN_CONFIG = 0x1A # 1 byte
|
|
|
|
|
|
|
|
|
|
|
|
|
-def _find_gpio_chip():
|
|
|
|
|
- """Find the right gpiochip for Raspberry Pi GPIO pins.
|
|
|
|
|
|
|
+def _check_spi_device_access() -> str:
|
|
|
|
|
+ """Check that the configured spidev exists and can be opened."""
|
|
|
|
|
+ spi_path = f"/dev/spidev{DRIVER_SPI_BUS}.{DRIVER_SPI_DEVICE}"
|
|
|
|
|
+ if not os.path.exists(spi_path):
|
|
|
|
|
+ raise FileNotFoundError(f"SPI device not found: {spi_path}")
|
|
|
|
|
|
|
|
- RPi 5 uses gpiochip4, RPi 4 uses gpiochip0.
|
|
|
|
|
- """
|
|
|
|
|
- for path in ["/dev/gpiochip4", "/dev/gpiochip0"]:
|
|
|
|
|
- try:
|
|
|
|
|
- chip = gpiod.Chip(path)
|
|
|
|
|
- info = chip.get_info()
|
|
|
|
|
- # RPi 4: pinctrl-bcm2711, RPi 5: pinctrl-rp1
|
|
|
|
|
- if "pinctrl" in info.label:
|
|
|
|
|
- return chip
|
|
|
|
|
- chip.close()
|
|
|
|
|
- except (FileNotFoundError, PermissionError, OSError):
|
|
|
|
|
- continue
|
|
|
|
|
- raise RuntimeError("Could not find Raspberry Pi GPIO chip")
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class PN5180:
|
|
|
|
|
- """Low-level driver for the PN5180 NFC frontend over SPI."""
|
|
|
|
|
-
|
|
|
|
|
- def __init__(
|
|
|
|
|
- self,
|
|
|
|
|
- spi_bus=0,
|
|
|
|
|
- spi_device=0,
|
|
|
|
|
- spi_speed_hz=500_000,
|
|
|
|
|
- busy_pin=BUSY_PIN,
|
|
|
|
|
- rst_pin=RST_PIN,
|
|
|
|
|
- nss_pin=NSS_PIN,
|
|
|
|
|
- ):
|
|
|
|
|
- # GPIO setup via libgpiod
|
|
|
|
|
- self._chip = _find_gpio_chip()
|
|
|
|
|
-
|
|
|
|
|
- try:
|
|
|
|
|
- self._busy_line = self._chip.request_lines(
|
|
|
|
|
- consumer="pn5180-diag",
|
|
|
|
|
- config={busy_pin: gpiod.LineSettings(direction=gpiod.line.Direction.INPUT)},
|
|
|
|
|
- )
|
|
|
|
|
- self._rst_line = self._chip.request_lines(
|
|
|
|
|
- consumer="pn5180-diag",
|
|
|
|
|
- config={
|
|
|
|
|
- rst_pin: gpiod.LineSettings(
|
|
|
|
|
- direction=gpiod.line.Direction.OUTPUT,
|
|
|
|
|
- output_value=gpiod.line.Value.ACTIVE,
|
|
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
- )
|
|
|
|
|
- self._nss_line = self._chip.request_lines(
|
|
|
|
|
- consumer="pn5180-diag",
|
|
|
|
|
- config={
|
|
|
|
|
- nss_pin: gpiod.LineSettings(
|
|
|
|
|
- direction=gpiod.line.Direction.OUTPUT,
|
|
|
|
|
- output_value=gpiod.line.Value.ACTIVE,
|
|
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
- )
|
|
|
|
|
- except OSError as e:
|
|
|
|
|
- self._chip.close()
|
|
|
|
|
- if getattr(e, "errno", None) == 16:
|
|
|
|
|
- raise RuntimeError(
|
|
|
|
|
- "GPIO line is busy (another process owns PN5180 pins). "
|
|
|
|
|
- "Stop spoolbuddy service before running diagnostics: "
|
|
|
|
|
- "sudo systemctl stop spoolbuddy"
|
|
|
|
|
- ) from e
|
|
|
|
|
- raise
|
|
|
|
|
- self._busy_pin = busy_pin
|
|
|
|
|
- self._rst_pin = rst_pin
|
|
|
|
|
- self._nss_pin = nss_pin
|
|
|
|
|
-
|
|
|
|
|
- # SPI setup - mode 0 (CPOL=0, CPHA=0), MSB first
|
|
|
|
|
- self._spi = spidev.SpiDev()
|
|
|
|
|
- self._spi.open(spi_bus, spi_device)
|
|
|
|
|
- self._spi.max_speed_hz = spi_speed_hz
|
|
|
|
|
- self._spi.mode = 0b00
|
|
|
|
|
- self._spi.bits_per_word = 8
|
|
|
|
|
- self._spi.no_cs = True
|
|
|
|
|
-
|
|
|
|
|
- def close(self):
|
|
|
|
|
- self._spi.close()
|
|
|
|
|
- self._busy_line.release()
|
|
|
|
|
- self._rst_line.release()
|
|
|
|
|
- self._nss_line.release()
|
|
|
|
|
- self._chip.close()
|
|
|
|
|
-
|
|
|
|
|
- # -- low-level helpers --------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- def _busy_is_high(self):
|
|
|
|
|
- return self._busy_line.get_value(self._busy_pin) == gpiod.line.Value.ACTIVE
|
|
|
|
|
-
|
|
|
|
|
- def _wait_busy(self, timeout_s=1.0):
|
|
|
|
|
- """Block until BUSY goes LOW (PN5180 ready)."""
|
|
|
|
|
- deadline = time.monotonic() + timeout_s
|
|
|
|
|
- while self._busy_is_high():
|
|
|
|
|
- if time.monotonic() > deadline:
|
|
|
|
|
- raise TimeoutError("PN5180 BUSY line did not go low")
|
|
|
|
|
- time.sleep(0.001)
|
|
|
|
|
-
|
|
|
|
|
- def _cs_low(self):
|
|
|
|
|
- self._nss_line.set_value(self._nss_pin, gpiod.line.Value.INACTIVE)
|
|
|
|
|
- time.sleep(0.000005)
|
|
|
|
|
-
|
|
|
|
|
- def _cs_high(self):
|
|
|
|
|
- self._nss_line.set_value(self._nss_pin, gpiod.line.Value.ACTIVE)
|
|
|
|
|
- time.sleep(0.000100)
|
|
|
|
|
-
|
|
|
|
|
- def _send_command(self, tx_data, rx_len=0):
|
|
|
|
|
- """Send an SPI command frame and optionally read a response frame.
|
|
|
|
|
-
|
|
|
|
|
- The PN5180 SPI protocol is half-duplex:
|
|
|
|
|
- 1. Send command frame (NSS held low for entire frame).
|
|
|
|
|
- 2. Wait for BUSY high then low (command processed).
|
|
|
|
|
- 3. If a response is expected, clock out rx_len bytes in a second frame.
|
|
|
|
|
- """
|
|
|
|
|
- self._wait_busy()
|
|
|
|
|
-
|
|
|
|
|
- # Transmit command (manual CS)
|
|
|
|
|
- self._cs_low()
|
|
|
|
|
- self._spi.xfer2(list(tx_data))
|
|
|
|
|
- self._cs_high()
|
|
|
|
|
-
|
|
|
|
|
- if rx_len == 0:
|
|
|
|
|
- # Write-only command - wait for processing
|
|
|
|
|
- time.sleep(0.001)
|
|
|
|
|
- self._wait_busy()
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
- # Wait for PN5180 to process command (BUSY goes high then low)
|
|
|
|
|
- time.sleep(0.001)
|
|
|
|
|
- self._wait_busy()
|
|
|
|
|
-
|
|
|
|
|
- # Read response (manual CS)
|
|
|
|
|
- self._cs_low()
|
|
|
|
|
- rx = self._spi.xfer2([0xFF] * rx_len)
|
|
|
|
|
- self._cs_high()
|
|
|
|
|
- time.sleep(0.001)
|
|
|
|
|
- self._wait_busy()
|
|
|
|
|
- return bytes(rx)
|
|
|
|
|
-
|
|
|
|
|
- # -- register operations ------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- def read_register(self, addr):
|
|
|
|
|
- """Read a 32-bit register. Returns int."""
|
|
|
|
|
- resp = self._send_command([CMD_READ_REGISTER, addr], rx_len=4)
|
|
|
|
|
- return int.from_bytes(resp, "little")
|
|
|
|
|
-
|
|
|
|
|
- def write_register(self, addr, value):
|
|
|
|
|
- """Write a 32-bit value to a register."""
|
|
|
|
|
- self._send_command(
|
|
|
|
|
- [
|
|
|
|
|
- CMD_WRITE_REGISTER,
|
|
|
|
|
- addr,
|
|
|
|
|
- value & 0xFF,
|
|
|
|
|
- (value >> 8) & 0xFF,
|
|
|
|
|
- (value >> 16) & 0xFF,
|
|
|
|
|
- (value >> 24) & 0xFF,
|
|
|
|
|
- ]
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ fd = os.open(spi_path, os.O_RDWR)
|
|
|
|
|
+ os.close(fd)
|
|
|
|
|
+ return spi_path
|
|
|
|
|
|
|
|
- def write_register_or_mask(self, addr, mask):
|
|
|
|
|
- self._send_command(
|
|
|
|
|
- [
|
|
|
|
|
- CMD_WRITE_REGISTER_OR_MASK,
|
|
|
|
|
- addr,
|
|
|
|
|
- mask & 0xFF,
|
|
|
|
|
- (mask >> 8) & 0xFF,
|
|
|
|
|
- (mask >> 16) & 0xFF,
|
|
|
|
|
- (mask >> 24) & 0xFF,
|
|
|
|
|
- ]
|
|
|
|
|
- )
|
|
|
|
|
|
|
|
|
|
- def write_register_and_mask(self, addr, mask):
|
|
|
|
|
- self._send_command(
|
|
|
|
|
- [
|
|
|
|
|
- CMD_WRITE_REGISTER_AND_MASK,
|
|
|
|
|
- addr,
|
|
|
|
|
- mask & 0xFF,
|
|
|
|
|
- (mask >> 8) & 0xFF,
|
|
|
|
|
- (mask >> 16) & 0xFF,
|
|
|
|
|
- (mask >> 24) & 0xFF,
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+def _self_test_control_pins(nfc: PN5180):
|
|
|
|
|
+ """Toggle NSS and RST pins and print observed line state.
|
|
|
|
|
+ Uses public set_pin/get_pin methods to avoid direct access to driver internals.
|
|
|
|
|
+ """
|
|
|
|
|
+ for pin_name, pin_num in (("NSS", DRIVER_NSS_PIN), ("RST", DRIVER_RST_PIN)):
|
|
|
|
|
+ nfc.set_pin(pin_num, True)
|
|
|
|
|
+ time.sleep(0.005)
|
|
|
|
|
+ active_state = nfc.get_pin(pin_num)
|
|
|
|
|
+
|
|
|
|
|
+ nfc.set_pin(pin_num, False)
|
|
|
|
|
+ time.sleep(0.005)
|
|
|
|
|
+ inactive_state = nfc.get_pin(pin_num)
|
|
|
|
|
+
|
|
|
|
|
+ # Restore idle-high level used by this driver.
|
|
|
|
|
+ nfc.set_pin(pin_num, True)
|
|
|
|
|
+
|
|
|
|
|
+ print(
|
|
|
|
|
+ f" {pin_name} pin {pin_num}: "
|
|
|
|
|
+ f"ACTIVE->{'ACTIVE' if active_state else 'INACTIVE'}, "
|
|
|
|
|
+ f"INACTIVE->{'ACTIVE' if inactive_state else 'INACTIVE'}"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- # -- EEPROM operations --------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- def read_eeprom(self, addr, length):
|
|
|
|
|
- """Read `length` bytes from EEPROM starting at `addr`."""
|
|
|
|
|
- return self._send_command([CMD_READ_EEPROM, addr, length], rx_len=length)
|
|
|
|
|
-
|
|
|
|
|
- # -- reset --------------------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- def reset(self):
|
|
|
|
|
- """Hardware-reset the PN5180 via the RST pin."""
|
|
|
|
|
- self._rst_line.set_value(self._rst_pin, gpiod.line.Value.INACTIVE)
|
|
|
|
|
- time.sleep(0.01)
|
|
|
|
|
- self._rst_line.set_value(self._rst_pin, gpiod.line.Value.ACTIVE)
|
|
|
|
|
- time.sleep(0.05)
|
|
|
|
|
- self._wait_busy(timeout_s=2.0)
|
|
|
|
|
- # Clear all IRQ flags
|
|
|
|
|
- self.write_register(REG_IRQ_CLEAR, 0xFFFFFFFF)
|
|
|
|
|
-
|
|
|
|
|
- # -- version / identity -------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- def get_product_version(self):
|
|
|
|
|
- data = self.read_eeprom(EEPROM_PRODUCT_VERSION, 2)
|
|
|
|
|
- return f"{data[1]}.{data[0]}"
|
|
|
|
|
-
|
|
|
|
|
- def get_firmware_version(self):
|
|
|
|
|
- data = self.read_eeprom(EEPROM_FIRMWARE_VERSION, 2)
|
|
|
|
|
- return f"{data[1]}.{data[0]}"
|
|
|
|
|
-
|
|
|
|
|
- def get_eeprom_version(self):
|
|
|
|
|
- data = self.read_eeprom(EEPROM_EEPROM_VERSION, 2)
|
|
|
|
|
- return f"{data[1]}.{data[0]}"
|
|
|
|
|
-
|
|
|
|
|
- def get_die_identifier(self):
|
|
|
|
|
- data = self.read_eeprom(EEPROM_DIE_IDENTIFIER, 16)
|
|
|
|
|
- return data.hex()
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
def run_diagnostics():
|
|
def run_diagnostics():
|
|
|
print("=" * 60)
|
|
print("=" * 60)
|
|
@@ -315,28 +99,71 @@ def run_diagnostics():
|
|
|
|
|
|
|
|
nfc = None
|
|
nfc = None
|
|
|
try:
|
|
try:
|
|
|
|
|
+ print("\n[1] SPI device check...")
|
|
|
|
|
+ spi_path = _check_spi_device_access()
|
|
|
|
|
+ print(f" SPI device OK: {spi_path}")
|
|
|
|
|
+
|
|
|
nfc = PN5180()
|
|
nfc = PN5180()
|
|
|
|
|
+
|
|
|
|
|
+ print("\n[2] Control pin self-test (NSS/RST)...")
|
|
|
|
|
+ _self_test_control_pins(nfc)
|
|
|
|
|
+
|
|
|
# Reset
|
|
# Reset
|
|
|
- print("\n[1] Hardware reset...")
|
|
|
|
|
|
|
+ print("\n[3] Hardware reset...")
|
|
|
nfc.reset()
|
|
nfc.reset()
|
|
|
print(" Reset OK")
|
|
print(" Reset OK")
|
|
|
|
|
|
|
|
# Version info
|
|
# Version info
|
|
|
- print("\n[2] Version info (EEPROM)")
|
|
|
|
|
- print(f" Product version : {nfc.get_product_version()}")
|
|
|
|
|
- print(f" Firmware version : {nfc.get_firmware_version()}")
|
|
|
|
|
- print(f" EEPROM version : {nfc.get_eeprom_version()}")
|
|
|
|
|
- print(f" Die identifier : {nfc.get_die_identifier()}")
|
|
|
|
|
|
|
+ print("\n[4] Version info (EEPROM)")
|
|
|
|
|
+ product = nfc.read_eeprom(EEPROM_PRODUCT_VERSION, 2)
|
|
|
|
|
+ firmware = nfc.read_eeprom(EEPROM_FIRMWARE_VERSION, 2)
|
|
|
|
|
+ eeprom = nfc.read_eeprom(EEPROM_EEPROM_VERSION, 2)
|
|
|
|
|
+ die_id = nfc.read_eeprom(EEPROM_DIE_IDENTIFIER, 16)
|
|
|
|
|
+
|
|
|
|
|
+ print(f" Product version : {product[1]}.{product[0]}")
|
|
|
|
|
+ print(f" Firmware version : {firmware[1]}.{firmware[0]}")
|
|
|
|
|
+ print(f" EEPROM version : {eeprom[1]}.{eeprom[0]}")
|
|
|
|
|
+ print(f" Die identifier : {die_id.hex()}")
|
|
|
|
|
|
|
|
# Register dump
|
|
# Register dump
|
|
|
- print("\n[3] Register dump")
|
|
|
|
|
- for addr, name in sorted(REGISTER_NAMES.items()):
|
|
|
|
|
- val = nfc.read_register(addr)
|
|
|
|
|
|
|
+ print("\n[5] Register dump")
|
|
|
|
|
+ # Use register names from the script (not in pn5180.py)
|
|
|
|
|
+ REGISTER_NAMES_DUMP = {
|
|
|
|
|
+ 0x00: "SYSTEM_CONFIG",
|
|
|
|
|
+ 0x01: "IRQ_ENABLE",
|
|
|
|
|
+ 0x02: "IRQ_STATUS",
|
|
|
|
|
+ 0x03: "IRQ_CLEAR",
|
|
|
|
|
+ 0x04: "TRANSCEIVE_CONTROL",
|
|
|
|
|
+ 0x0C: "TIMER1_RELOAD",
|
|
|
|
|
+ 0x0F: "TIMER1_CONFIG",
|
|
|
|
|
+ 0x11: "RX_WAIT_CONFIG",
|
|
|
|
|
+ 0x12: "CRC_RX_CONFIG",
|
|
|
|
|
+ 0x13: "RX_STATUS",
|
|
|
|
|
+ 0x19: "CRC_TX_CONFIG",
|
|
|
|
|
+ 0x1A: "SIGPRO_CONFIG",
|
|
|
|
|
+ 0x1D: "RF_STATUS",
|
|
|
|
|
+ 0x24: "SYSTEM_STATUS",
|
|
|
|
|
+ 0x25: "TEMP_CONTROL",
|
|
|
|
|
+ }
|
|
|
|
|
+ for addr, name in sorted(REGISTER_NAMES_DUMP.items()):
|
|
|
|
|
+ val = nfc.read_reg(addr)
|
|
|
print(f" 0x{addr:02X} {name:<24s} = 0x{val:08X}")
|
|
print(f" 0x{addr:02X} {name:<24s} = 0x{val:08X}")
|
|
|
|
|
|
|
|
|
|
+ # SIGPRO_CONFIG ISO/IEC14443 mode check
|
|
|
|
|
+ sigpro_val = nfc.read_reg(REG_SIGPRO_CONFIG)
|
|
|
|
|
+ sigpro_mode = (sigpro_val >> 0) & 0b111
|
|
|
|
|
+ baudrate_map = {
|
|
|
|
|
+ 0b100: "106 kBd (ISO/IEC14443 type A/B)",
|
|
|
|
|
+ 0b101: "212 kBd (FeliCa 212 kBd)",
|
|
|
|
|
+ 0b110: "424 kBd (FeliCa 424 kBd)",
|
|
|
|
|
+ 0b111: "848 kBd",
|
|
|
|
|
+ }
|
|
|
|
|
+ baudrate_str = baudrate_map.get(sigpro_mode, "Unknown or reserved")
|
|
|
|
|
+ print(f"\n[5b] SIGPRO_CONFIG (0x1A) bits 2:0 = 0b{sigpro_mode:03b} ({baudrate_str})")
|
|
|
|
|
+
|
|
|
# IRQ status breakdown
|
|
# IRQ status breakdown
|
|
|
- irq = nfc.read_register(REG_IRQ_STATUS)
|
|
|
|
|
- print(f"\n[4] IRQ status flags (0x{irq:08X})")
|
|
|
|
|
|
|
+ irq = nfc.read_reg(REG_IRQ_STATUS)
|
|
|
|
|
+ print(f"\n[6] IRQ status flags (0x{irq:08X})")
|
|
|
irq_flags = [
|
|
irq_flags = [
|
|
|
(0, "RX_IRQ"),
|
|
(0, "RX_IRQ"),
|
|
|
(1, "TX_IRQ"),
|
|
(1, "TX_IRQ"),
|
|
@@ -356,20 +183,48 @@ def run_diagnostics():
|
|
|
print(f" bit {bit:2d}: {name:<28s} [{state}]")
|
|
print(f" bit {bit:2d}: {name:<28s} [{state}]")
|
|
|
|
|
|
|
|
# RF status
|
|
# RF status
|
|
|
- rf = nfc.read_register(REG_RF_STATUS)
|
|
|
|
|
- print(f"\n[5] RF status (0x{rf:08X})")
|
|
|
|
|
|
|
+ rf = nfc.read_reg(REG_RF_STATUS)
|
|
|
|
|
+ print(f"\n[7] RF status (0x{rf:08X})")
|
|
|
tx_rf_on = bool(rf & (1 << 0))
|
|
tx_rf_on = bool(rf & (1 << 0))
|
|
|
rx_en = bool(rf & (1 << 1))
|
|
rx_en = bool(rf & (1 << 1))
|
|
|
print(f" TX RF active : {tx_rf_on}")
|
|
print(f" TX RF active : {tx_rf_on}")
|
|
|
print(f" RX enabled : {rx_en}")
|
|
print(f" RX enabled : {rx_en}")
|
|
|
|
|
|
|
|
# System status
|
|
# System status
|
|
|
- sys_stat = nfc.read_register(REG_SYSTEM_STATUS)
|
|
|
|
|
- print(f"\n[6] System status (0x{sys_stat:08X})")
|
|
|
|
|
|
|
+ sys_stat = nfc.read_reg(REG_SYSTEM_STATUS)
|
|
|
|
|
+ print(f"\n[8] System status (0x{sys_stat:08X})")
|
|
|
|
|
+
|
|
|
|
|
+ # System status bit breakdown
|
|
|
|
|
+ sys_stat_bits = [
|
|
|
|
|
+ (9, "LDO_TVDD_OK"),
|
|
|
|
|
+ (8, "PARAMETER_ERROR"),
|
|
|
|
|
+ (7, "SYNTAX_ERROR"),
|
|
|
|
|
+ (6, "SEMANTIC_ERROR"),
|
|
|
|
|
+ (5, "STBY_PREVENT_RFLD"),
|
|
|
|
|
+ (4, "BOOT_TEMP"),
|
|
|
|
|
+ (3, "BOOT_SOFT_RESET"),
|
|
|
|
|
+ (2, "BOOT_WUC"),
|
|
|
|
|
+ (1, "BOOT_RFLD"),
|
|
|
|
|
+ (0, "BOOT_POR"),
|
|
|
|
|
+ ]
|
|
|
|
|
+ for bit, symbol in sys_stat_bits:
|
|
|
|
|
+ state = "SET" if sys_stat & (1 << bit) else "---"
|
|
|
|
|
+ print(f" bit {bit:2d}: {symbol:<18s} [{state}]")
|
|
|
|
|
|
|
|
# Temperature
|
|
# Temperature
|
|
|
- temp_ctrl = nfc.read_register(REG_TEMP_CONTROL)
|
|
|
|
|
- print(f"\n[7] Temp control register (0x{temp_ctrl:08X})")
|
|
|
|
|
|
|
+ temp_ctrl = nfc.read_reg(REG_TEMP_CONTROL)
|
|
|
|
|
+ print(f"\n[9] Temp control register (0x{temp_ctrl:08X})")
|
|
|
|
|
+
|
|
|
|
|
+ # TEMP_DELTA bits 1:0
|
|
|
|
|
+ temp_delta = (temp_ctrl >> 0) & 0b11
|
|
|
|
|
+ temp_delta_map = {
|
|
|
|
|
+ 0b00: "85°C",
|
|
|
|
|
+ 0b01: "115°C",
|
|
|
|
|
+ 0b10: "125°C",
|
|
|
|
|
+ 0b11: "135°C",
|
|
|
|
|
+ }
|
|
|
|
|
+ temp_delta_str = temp_delta_map.get(temp_delta, "Unknown")
|
|
|
|
|
+ print(f" bits 1:0 TEMP_DELTA = 0b{temp_delta:02b} ({temp_delta_str})")
|
|
|
|
|
|
|
|
print("\n" + "=" * 60)
|
|
print("\n" + "=" * 60)
|
|
|
print("Diagnostics complete - PN5180 is responding over SPI.")
|
|
print("Diagnostics complete - PN5180 is responding over SPI.")
|