Files
xblink/CLAUDE.md
michael bae64c1e3a Initial project scaffold for xblink NFC-powered LED implant
Set up Rust embedded project targeting SAMD21 (thumbv6m-none-eabi) with
XIAO M0 BSP for dev board prototyping. Includes LP5562 EN pin control
on D0/A0, project documentation (README, CLAUDE.md), phased status
tracker, and detailed development plan covering LP5562 driver integration,
NTAG5Link I2C driver, pattern storage format, power management, NFC
communication protocol, recovery mode, and firmware update strategy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:32:30 -08:00

4.8 KiB

xblink Development Guide

Embedded Rust firmware for a battery-free, NFC-powered LED implant. The NTAG5Link harvests energy from an NFC field and provides EEPROM storage for LED patterns. A SAMD21E MCU reads patterns from EEPROM, programs LP5562 execution engines, then sleeps while the LP5562 autonomously drives RGBW LEDs.

Build Commands

# Build release firmware
cargo build --release

# Flash via UF2 bootloader (XIAO M0: double-tap RST to enter bootloader)
cargo hf2 --release

Target

  • Architecture: thumbv6m-none-eabi (ARM Cortex-M0+)
  • Dev board: Seeed XIAO M0 (SAMD21G18A) — will port to bare SAMD21E18A later
  • LED driver: LP5562EVM (TI evaluation module, RGBW, I2C addr 0x30)
  • NFC: NTAG5Link Click board (MikroElektronika)

Dependencies

Crate Version Purpose
xiao_m0 0.13 Board support package (dev board phase)
panic-halt 0.2 Minimal panic handler for no_std
cortex-m 0.7 Cortex-M runtime, critical-section-single-core feature
embedded-hal 1.0.0 Hardware abstraction traits (I2C, GPIO, delay)

When porting to bare SAMD21E: replace xiao_m0 with atsamd-hal = { version = "0.17", features = ["samd21e"] } and add cortex-m-rt = "0.7".

Project Structure

src/
  main.rs          # Entry point: boot, pattern load, sleep/wake loop
  led/
    mod.rs         # LedController trait + re-exports
    lp5562.rs      # LP5562 driver (from ../ntag5-samd21-lp562/)
    simple_pwm.rs  # Single-color LED driver (GPIO PWM)
  ntag5/
    mod.rs         # NTAG5Link I2C slave driver (MCU-side)
    registers.rs   # Register map and config constants
    eeprom.rs      # EEPROM read/write
    sram.rs        # SRAM mailbox for NFC pass-through
  pattern/
    mod.rs         # Pattern format, parser, serializer
    engine.rs      # LP5562 engine program builder from patterns

Architecture Conventions

  • no_std only: No heap allocation. Fixed-size arrays and stack-only data structures.
  • embedded-hal generics: All hardware drivers must be generic over embedded_hal::i2c::I2c (1.0 traits). Never use concrete HAL types in driver code.
  • LedController trait: LED controllers implement the LedController trait defined in src/led/mod.rs. This enables modular support for LP5562, single-color PWM, and future LED driver ICs.
  • Error types: Use Error<E> enum wrapping underlying I2C error with From<E> impl (see LP5562 driver pattern).
  • Register addresses: Place in a reg submodule as pub const values.
  • const fn: Prefer const fn where possible (see EngineCommand builder in LP5562 driver).
  • No unsafe: Avoid unless absolutely necessary for hardware access.

Key I2C Addresses

Device Address Notes
LP5562 0x30 ADDR_SEL pins both low (LP5562EVM default)
NTAG5Link 0x54 Default NTP53x2 I2C slave address

The MCU accesses NTAG5Link as a standard I2C slave — plain register read/write, NOT the NFC-side ISO15693 custom commands used by the Python ntag5sensor tooling.

Region Address Range Size Notes
Session registers 0x00-0x06 7 bytes Volatile, runtime config
Configuration 0x37-0x3F Varies Persistent, EEPROM-backed
EH config 0x3D 1 byte Energy harvesting voltage/current
SRAM 0xF8-0xFF 256 bytes 64 x 4-byte blocks, volatile
EEPROM user memory blocks 0x00-0x1FF 2048 bytes 512 x 4-byte blocks

Key config constants (from ../ntag5sensor/vicinity/ntag5link.py):

  • CONFIG_1_USE_CASE_CONF_I2C_SLAVE = 0 << 4 — NTAG5 as I2C slave (our mode)
  • CONFIG_1_ARBITER_MODE_SRAM_PASSTHROUGH = 2 << 2 — SRAM pass-through for NFC↔I2C
  • CONFIG_1_SRAM_ENABLE = 1 << 1 — Enable SRAM access
  • CONFIG_0_EH_MODE_LOW_FIELD_STRENGTH = 2 << 2 — EH mode for phone NFC

Hardware Wiring (Dev Board)

XIAO Pin Connection Function
A4 (SDA) LP5562 SDA, NTAG5 SDA Shared I2C data
A5 (SCL) LP5562 SCL, NTAG5 SCL Shared I2C clock
D0/A0 LP5562 EN Hardware enable (GPIO, active high)
TBD NTAG5 FD pin Field detect / SRAM write indication (EIC wake)
TBD Hall sensor Recovery mode trigger (EIC wake)

Testing

  • Hardware: XIAO M0 + LP5562EVM + NTAG5Link Click (when jumpers available)
  • PCSC reader: Use ../ntag5sensor/ Python tooling with ACR1552 reader
  • Phone NFC: VivoKey RawNFC app for SRAM mailbox testing
  • Phone app: DT NFC Identifier for basic tag info

Sibling Projects

  • ../ntag5-samd21-lp562/ — LP5562 driver source (src/lp5562.rs), reference main.rs boot sequence
  • ../ntag5sensor/ — NTAG5Link command reference (vicinity/ntag5link.py), I2C patterns (vicinity/i2cbase.py)