door/outside/src/scanner.rs

86 lines
2.5 KiB
Rust

use core::sync::atomic::AtomicBool;
use embassy_rp::gpio::Input;
use embassy_rp::multicore::spawn_core1;
use embassy_rp::multicore::Stack;
use embassy_rp::peripherals::CORE1;
use embassy_rp::peripherals::PIN_16;
use embassy_rp::peripherals::PIN_17;
use embassy_time::Timer;
use log::info;
use super::CHANNEL;
use super::BIT;
use super::READ_CARD;
/// disable scanner when doing emf heavy operations
pub static LOCKOUT: AtomicBool = AtomicBool::new(false);
#[embassy_executor::task]
pub(crate) async fn data_extractor() -> ! {
let mut last_bit = 0;
loop {
Timer::after_millis(75).await;
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
let bit = BIT.load(core::sync::atomic::Ordering::SeqCst);
if bit == last_bit {
if card !=0 {
info!("read a card: {card:#16x}");
if LOCKOUT.load(core::sync::atomic::Ordering::Relaxed) {
info!("scanner disabled");
} else {
CHANNEL.send(card).await;
}
}
critical_section::with(|cs| {
READ_CARD.replace(cs, 0);
});
}
last_bit = bit;
}
}
pub fn spawn_poller(core: CORE1, data_0: PIN_17, data_1: PIN_16) {
let data_0= Input::new(data_0, embassy_rp::gpio::Pull::None);
let data_1= Input::new(data_1, embassy_rp::gpio::Pull::None);
let mut partial: u64 = 0;
let mut bit: u8 = 0;
let mut prev: (bool,bool) = (false,false);
static mut CORE1_STACK: Stack<4096> = Stack::new();
spawn_core1(core, unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || {
loop {
let current = (data_0.is_low(), data_1.is_low());
if current.1 && !prev.1 {
partial |= 1 << bit;
bit += 1;
}
if current.0 && !prev.0 {
partial &= !(1u64).rotate_left(bit as u32);
bit += 1;
}
prev=current;
critical_section::with(|cs| {
let mut foreign_partial = READ_CARD.borrow_ref_mut(cs);
// may or may not be sound, should work fine given no noise on the signal
if *foreign_partial != partial && !current.0 && !current.1 {
bit = 0;
partial = *foreign_partial;
}
*foreign_partial = partial;
});
BIT.store(bit, core::sync::atomic::Ordering::SeqCst);
}
});
}