diff --git a/Cargo.lock b/Cargo.lock index 795d024..19bc895 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,6 +320,7 @@ dependencies = [ "esp-rtos", "ili9341", "log", + "ndef", "pn532", ] @@ -569,6 +570,26 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "digest" version = "0.10.7" @@ -1981,6 +2002,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "ndef" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39081400340c14a9fcbb0122c311aca4e34ec2d19e3136613638ae7e2a362dbc" +dependencies = [ + "derive_more", + "heapless 0.8.0", + "rustversion", +] + [[package]] name = "nonmax" version = "0.5.5" diff --git a/Cargo.toml b/Cargo.toml index 4133b04..eeaf461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,8 @@ embedded-graphics = "0.8.2" embedded-graphics-core = "0.4.1" base64 = { version = "0.22", default-features = false, features = ["alloc"] } pn532 = "0.5.0" +ndef = "0.5.0" + diff --git a/src/bin/main.rs b/src/bin/main.rs index e9861ae..e09f649 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -94,7 +94,7 @@ async fn main(spawner: Spawner) { } loop { - if let Some(card_data) = nfc_driver.read_card(timeout) { + if let Ok(card_data) = nfc_driver.read_card_data() { log::info!("NFC Card Read: {:?}", card_data); } diff --git a/src/drivers/nfc_pn532.rs b/src/drivers/nfc_pn532.rs index 12cf8f6..831d70b 100644 --- a/src/drivers/nfc_pn532.rs +++ b/src/drivers/nfc_pn532.rs @@ -1,3 +1,4 @@ +use alloc::vec::Vec; use core::convert::Infallible; use esp_hal::gpio::interconnect::{PeripheralInput, PeripheralOutput}; use esp_hal::i2c::master::{Config as I2cConfig, I2c}; @@ -38,8 +39,7 @@ impl pn532::CountDown for TimerWrapper { where T: Into, { - // without this debug log, it works worse: stuck in NFC card search without ever returning. - self.start = esp_println::dbg!(Instant::now()); + self.start = Instant::now(); self.duration = timeout.into(); self.counter = 0; } @@ -47,9 +47,6 @@ impl pn532::CountDown for TimerWrapper { fn wait(&mut self) -> nb::Result<(), Infallible> { let elapsed = self.start.elapsed(); self.counter += 1; - if self.counter.is_multiple_of(1) { - info!("Elapsed: {elapsed}"); - } if elapsed >= self.duration { Ok(()) } else { @@ -71,7 +68,7 @@ impl<'a> NfcPn532Driver<'a> { SDA: PeripheralInput<'static> + PeripheralOutput<'static>, SCL: PeripheralInput<'static> + PeripheralOutput<'static>, { - let config = I2cConfig::default().with_frequency(Rate::from_khz(100)); + let config = I2cConfig::default().with_frequency(Rate::from_khz(20)); let i2c = I2c::new(i2c0, config) .expect("Failed to init I2C") .with_sda(sda) @@ -95,24 +92,55 @@ impl<'a> NfcPn532Driver<'a> { } } - pub fn read_card(&mut self, timeout: Duration) -> Option<[u8; 4]> { - if let Ok(uid) = self.pn532.process(&Request::INLIST_ONE_ISO_A_TARGET, 7, timeout) { - info!("uid = {uid:?}"); - if let Ok(result) = self.pn532.process(&Request::ntag_read(10), 17, timeout) { - info!("page 10: {:?}", &result[1..5]); - let mut data = [0u8; 4]; - data.copy_from_slice(&result[1..5]); - Some(data) - } else { - None + pub fn poll_target(&mut self, timeout: Duration) -> Result<(), ()> { + match self.pn532.process(&Request::INLIST_ONE_ISO_A_TARGET, 23, timeout) { + Ok(uid) => { + info!("uid = {uid:?}"); + Ok(()) + } + Err(e) => { + info!("No NFC card found: {e:?}"); + Err(()) } - } else { - info!("No NFC card found."); - None } } + pub fn parse_nfc_page(iteration: u8, bytes: &[u8]) -> Result<[u8; 4], ()> { + let success = bytes.first().is_some_and(|x| *x == 0); + if success { + let mut arr = [0; 4]; + arr.copy_from_slice(&bytes[1..5]); + Ok(arr) + } else { + info!("err {iteration}: {:02x?}", bytes); + Err(()) + } + } + + pub fn read_card_data(&mut self) -> Result, ()> { + let ms_1000 = Duration::from_millis(1000); + self.poll_target(Duration::from_secs(10))?; + + let mut data: Vec = Vec::with_capacity(858); + + for i in 0x04..=230 { + let mut parse_result = Err(()); + while parse_result.is_err() { + let Ok(result) = self.pn532.process(&Request::ntag_read(i), 17, ms_1000) else { + continue; + }; + parse_result = Self::parse_nfc_page(i, result); + } + let bytes = parse_result.unwrap(); + data.extend(bytes); + } + + info!("Full data: {data:02x?}"); + Ok(data) + } + pub fn device_mut(&mut self) -> &mut Pn532Device<'a> { &mut self.pn532 } } +