Added NFC implementation into refactored structure #25

Merged
ede1998 merged 2 commits from rust-nfc-refactored into main 2026-08-02 16:48:31 +02:00
4 changed files with 82 additions and 20 deletions
Showing only changes of commit 7ce3a60a08 - Show all commits
Generated
+32
View File
@@ -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"
+2
View File
@@ -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"
+1 -1
View File
@@ -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);
}
+47 -19
View File
@@ -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<Self::Time>,
{
// 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<Vec<u8>, ()> {
let ms_1000 = Duration::from_millis(1000);
self.poll_target(Duration::from_secs(10))?;
let mut data: Vec<u8> = 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
}
}