use bitvec::prelude::*;
use esp_idf_svc::hal::gpio::*;
use esp_idf_svc::hal::peripherals::Peripherals;
use itertools::Itertools;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
static mut WIEGAND: BitArr!(for 26, in u32, Msb0) = BitArray::<_, _>::ZERO;
static BIT_COUNT: AtomicU32 = AtomicU32::new(0);
static BIT_RECEIVED: AtomicBool = AtomicBool::new(false);
fn gpio0_int_callback() {
let bit_count = BIT_COUNT.load(Ordering::SeqCst);
unsafe { WIEGAND.set(bit_count.try_into().unwrap(), false); }
inc_bit_count();
}
fn gpio1_int_callback() {
let bit_count = BIT_COUNT.load(Ordering::SeqCst);
unsafe { WIEGAND.set(bit_count.try_into().unwrap(), true); }
inc_bit_count();
}
fn inc_bit_count() {
let bit_count = BIT_COUNT.load(Ordering::SeqCst);
BIT_COUNT.store(bit_count.wrapping_add(1), Ordering::SeqCst);
BIT_RECEIVED.store(true, Ordering::SeqCst);
}
fn main() -> anyhow::Result<()> {
esp_idf_svc::sys::link_patches();
let peripherals = Peripherals::take()?;
let mut btn0 = PinDriver::input(peripherals.pins.gpio0)?;
btn0.set_pull(Pull::Up)?;
btn0.set_interrupt_type(InterruptType::NegEdge)?;
unsafe { btn0.subscribe(gpio0_int_callback)? }
btn0.enable_interrupt()?;
let mut btn1 = PinDriver::input(peripherals.pins.gpio1)?;
btn1.set_pull(Pull::Up)?;
btn1.set_interrupt_type(InterruptType::NegEdge)?;
unsafe { btn1.subscribe(gpio1_int_callback)? }
btn1.enable_interrupt()?;
println!("Waiting to receive");
loop {
if BIT_RECEIVED.load(Ordering::SeqCst) {
BIT_RECEIVED.store(false, Ordering::SeqCst);
btn0.enable_interrupt()?;
btn1.enable_interrupt()?;
if BIT_COUNT.load(Ordering::SeqCst) == 26 {
BIT_COUNT.store(0, Ordering::SeqCst);
unsafe {
let s = WIEGAND[1..24].chunks(8)
.map(|x| x.load::<u8>())
.map(|x| format!("{:02X}", x))
.join(" ");
println!("{}", s);
WIEGAND = BitArray::ZERO;
}
}
}
}
}