Add NTAG5 SRAM read/write and FD pin config for M6 mailbox

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
michael
2026-03-05 16:13:06 -08:00
parent 2fade7ad8b
commit a6f8c70051

View File

@@ -18,6 +18,17 @@ pub const SESSION_CONFIG_REG: u16 = 0x10A1; // CONFIG_0_REG, CONFIG_1_REG, CONFI
pub const SESSION_EH_CONFIG_REG: u16 = 0x10A7; // EH_CONFIG_REG, RFU pub const SESSION_EH_CONFIG_REG: u16 = 0x10A7; // EH_CONFIG_REG, RFU
pub const SESSION_I2C_SLAVE_REG: u16 = 0x10A9; // I2C_SLAVE_ADDR_REG, I2C_SLAVE_CONFIG_REG pub const SESSION_I2C_SLAVE_REG: u16 = 0x10A9; // I2C_SLAVE_ADDR_REG, I2C_SLAVE_CONFIG_REG
// SRAM I2C block address range (64 blocks × 4 bytes = 256 bytes)
pub const SRAM_BASE_BLOCK: u16 = 0x10F8;
pub const SRAM_BLOCK_COUNT: u16 = 64;
pub const SRAM_SIZE: usize = 256;
// Session register for ED/FD pin configuration
pub const SESSION_ED_FD_PIN_CFG: u16 = 0x10A3;
// FD pin mode: active on SRAM write by RF, cleared on I2C read
pub const FD_MODE_SRAM_RF_WRITE: u8 = 0x04;
// EEPROM user memory I2C block addresses // EEPROM user memory I2C block addresses
// Block 0 = CC (capability container), blocks 1+ = NDEF data // Block 0 = CC (capability container), blocks 1+ = NDEF data
pub const EEPROM_BLOCK_0: u16 = 0x0000; pub const EEPROM_BLOCK_0: u16 = 0x0000;
@@ -143,6 +154,47 @@ where
Ok(buf[0]) Ok(buf[0])
} }
/// Write a single session register byte (WRITE REGISTER command).
/// Protocol: write [BL_AD1, BL_AD0, REGA, MASK, REGDATA].
/// The MASK selects which bits to modify (1 = modify, 0 = keep).
pub fn write_register(&mut self, block: u16, reg_addr: u8, mask: u8, data: u8) -> Result<(), E> {
let addr_bytes = block.to_be_bytes();
self.i2c.write(
self.addr,
&[addr_bytes[0], addr_bytes[1], reg_addr, mask, data],
)
}
// ---- SRAM access ----
/// Read N bytes from SRAM starting at byte offset 0.
/// SRAM is at I2C blocks 0x10F8-0x10FF (64 blocks × 4 bytes = 256 bytes).
/// Always reads from the start of SRAM (block-aligned).
pub fn read_sram(&mut self, buf: &mut [u8]) -> Result<(), E> {
self.read_memory(SRAM_BASE_BLOCK, buf)
}
/// Write data to SRAM starting at block offset from SRAM base.
/// Data length must be a multiple of 4 (NTAG5 block size).
pub fn write_sram_blocks(&mut self, block_offset: u16, data: &[u8]) -> Result<(), E> {
for (i, chunk) in data.chunks(4).enumerate() {
let mut block_data = [0u8; 4];
for (j, &b) in chunk.iter().enumerate() {
block_data[j] = b;
}
self.write_memory_block(SRAM_BASE_BLOCK + block_offset + i as u16, &block_data)?;
}
Ok(())
}
/// Configure FD pin for SRAM-write-by-RF indication.
/// FD goes low when phone writes to SRAM, returns high when MCU reads SRAM.
pub fn configure_fd_sram_write(&mut self) -> Result<(), E> {
// ED_FD_PIN_CFG register index 1 within the session block
// Bits 2:0 control FD output mode
self.write_register(SESSION_ED_FD_PIN_CFG, 0x01, 0x07, FD_MODE_SRAM_RF_WRITE)
}
// ---- Config check ---- // ---- Config check ----
/// Read session registers and compare against expected xblink config. /// Read session registers and compare against expected xblink config.