use esp_hal::gpio::{Input, InputConfig, Pull};
use esp_hal::peripherals::GPIO11;
use oxstack_drivers::tca8418::{self, Event, FIFO_DEPTH, Matrix, Tca8418};
use oxstack_input::{KeyEvent, KeyboardState, cardputer};
use crate::i2c::{SysI2cBus, SysI2cDevice, device};
pub type Error = embassy_embedded_hal::shared_bus::I2cDeviceError<esp_hal::i2c::master::Error>;
const MATRIX: Matrix = Matrix::new(cardputer::ADV_MATRIX_ROWS, cardputer::ADV_MATRIX_COLS);
#[allow(missing_docs)]
pub struct KeyboardResources<'d> {
pub int: GPIO11<'d>,
}
reborrow_group!(KeyboardResources { int });
impl<'d> KeyboardResources<'d> {
pub async fn init(&mut self, bus: &'static SysI2cBus) -> Result<Keyboard<'_>, Error> {
let int = Input::new(
self.int.reborrow(),
InputConfig::default().with_pull(Pull::Up),
);
let mut scanner = Tca8418::new(device(bus), tca8418::DEFAULT_ADDRESS);
scanner.configure(MATRIX).await?;
Ok(Keyboard {
scanner,
int,
state: KeyboardState::new(),
fifo: [0; FIFO_DEPTH],
pos: 0,
len: 0,
})
}
}
pub struct Keyboard<'d> {
scanner: Tca8418<SysI2cDevice>,
int: Input<'d>,
state: KeyboardState,
fifo: [u8; FIFO_DEPTH],
pos: u8,
len: u8,
}
impl Keyboard<'_> {
pub async fn next_event(&mut self) -> Result<KeyEvent, Error> {
loop {
while self.pos < self.len {
let raw = self.fifo[usize::from(self.pos)];
self.pos += 1;
if let Some(Event::Key(k)) = Event::decode(raw)
&& let Some(key) = cardputer::from_adv_matrix(k.row, k.col)
{
return Ok(self.state.apply(key, k.pressed));
}
}
self.int.wait_for_low().await;
let n = self.scanner.drain(&mut self.fifo).await?.len();
self.scanner.clear_interrupts().await?;
(self.pos, self.len) = (0, n as u8);
}
}
pub fn state(&self) -> &KeyboardState {
&self.state
}
}