Add card detection
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
use core::sync::atomic::{AtomicPtr, Ordering};
|
||||
use defmt::Debug2Format;
|
||||
use embassy_sync::once_lock::OnceLock;
|
||||
use embassy_time::{Delay, Timer};
|
||||
use esp_hal::gpio;
|
||||
use esp_hal::rng::Trng;
|
||||
use lorawan_device::RngCore;
|
||||
use pn532::felica::FelicaBlock;
|
||||
use pn532::Pn532;
|
||||
use crate::types::{LoraPublisher, SharedI2c};
|
||||
|
||||
static CARD_KEY: OnceLock<heapless::Vec<u8, 16>> = OnceLock::new();
|
||||
|
||||
fn get_card_key() -> &'static heapless::Vec<u8, 16> {
|
||||
CARD_KEY.get_or_init(|| {
|
||||
let hex_string = env!("CARD_KEY");
|
||||
let mut buffer = [0u8; 16];
|
||||
hex::decode_to_slice(hex_string, &mut buffer).unwrap();
|
||||
heapless::Vec::from_array(buffer)
|
||||
})
|
||||
}
|
||||
|
||||
pub struct CardReader<'a> {
|
||||
driver: Pn532<pn532::I2cInterface<SharedI2c<'a>, Delay, pn532::NoReset, gpio::Input<'a>>>
|
||||
}
|
||||
|
||||
impl<'a> CardReader<'a> {
|
||||
pub fn new(i2c: SharedI2c<'a>, irq: gpio::Input<'a>) -> Self {
|
||||
Self {
|
||||
driver: Pn532::new(pn532::I2cInterface::with_irq(i2c, Delay, irq))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self) -> Result<(), crate::error::Error> {
|
||||
self.driver.sam_config()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn start_card_reader(
|
||||
mut card_reader: CardReader<'static>,
|
||||
mut publisher: LoraPublisher<'static>,
|
||||
mut trng: Trng
|
||||
) -> () {
|
||||
let card_key = get_card_key();
|
||||
let mut rc = [0u8; 16];
|
||||
trng.fill_bytes(&mut rc);
|
||||
defmt::trace!("card_key: {}", hex::encode_upper(card_key));
|
||||
|
||||
loop {
|
||||
Timer::after_millis(50).await;
|
||||
let poll_result = match card_reader.driver.felica_polling(0xFFFF, 0x01, 1000) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader driver error: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let Some(res) = poll_result else {
|
||||
defmt::trace!("No card detected");
|
||||
continue;
|
||||
};
|
||||
defmt::info!("Polling card: {}", Debug2Format(&res));
|
||||
|
||||
match card_reader.driver.felica_release() {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader release error: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// InRelease switches the RF field off when no target remains
|
||||
// (UM0701-02 §7.3.11), so re-enable it before the next poll.
|
||||
if let Err(e) = card_reader.driver.set_rf_field(0x00, 0x01) {
|
||||
defmt::error!("card_reader RF field error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user