From 8cadd10ea7c7c1c85618011294ee55ca3e12ecd1 Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Mon, 23 Jun 2025 18:48:52 -0600 Subject: [PATCH] fix keyboard read regs --- src/main.rs | 6 ++-- src/peripherals/battery.rs | 20 +++++++++++ src/{ => peripherals}/keyboard.rs | 57 ++++++++++++++++++++++--------- src/peripherals/mod.rs | 56 ++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 19 deletions(-) create mode 100644 src/peripherals/battery.rs rename src/{ => peripherals}/keyboard.rs (69%) create mode 100644 src/peripherals/mod.rs diff --git a/src/main.rs b/src/main.rs index f1608e8..68773f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,8 +18,8 @@ use embedded_hal_bus::spi::ExclusiveDevice; use embedded_sdmmc::asynchronous::{File, SdCard, ShortFileName, VolumeIdx, VolumeManager}; use static_cell::StaticCell; -mod keyboard; -use keyboard::KeyEvent; +mod peripherals; +use peripherals::{keyboard::KeyEvent, peripherals_task}; embassy_rp::bind_interrupts!(struct Irqs { I2C1_IRQ => i2c::InterruptHandler; @@ -36,6 +36,6 @@ async fn main(spawner: Spawner) { let config = embassy_rp::i2c::Config::default(); let bus = embassy_rp::i2c::I2c::new_async(p.I2C1, p.PIN_27, p.PIN_26, Irqs, config); spawner - .spawn(keyboard::keyboard(bus, keyboard_events.sender())) + .spawn(peripherals_task(bus, keyboard_events.sender())) .unwrap(); } diff --git a/src/peripherals/battery.rs b/src/peripherals/battery.rs new file mode 100644 index 0000000..cd634ad --- /dev/null +++ b/src/peripherals/battery.rs @@ -0,0 +1,20 @@ +use embassy_rp::{ + i2c::{Async, I2c}, + peripherals::I2C1, +}; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, watch::Watch}; + +const REG_ID_BAT: u8 = 0x0b; + +pub static BATTERY_PCT: Watch = Watch::new(); + +pub async fn read_battery(i2c: &mut I2c<'static, I2C1, Async>) { + let mut buf = [0_u8; 2]; + i2c.write_read_async(super::MCU_ADDR, [REG_ID_BAT], &mut buf) + .await + .unwrap(); + + if buf[0] == REG_ID_BAT { + BATTERY_PCT.sender().send(buf[0]); + } +} diff --git a/src/keyboard.rs b/src/peripherals/keyboard.rs similarity index 69% rename from src/keyboard.rs rename to src/peripherals/keyboard.rs index 875e8b9..5f54aad 100644 --- a/src/keyboard.rs +++ b/src/peripherals/keyboard.rs @@ -2,32 +2,57 @@ use embassy_rp::{ i2c::{Async, I2c}, peripherals::I2C1, }; -use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Sender}; +use embassy_sync::{ + blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, + channel::Sender, +}; -const KEYBOARD_ADDR: u8 = 0x1F; +const REG_ID_KEY: u8 = 0x04; +const REG_ID_FIF: u8 = 0x09; -pub struct KeyEvent { - key: KeyCode, - state: KeyState, -} +const KEY_CAPSLOCK: u8 = 1 << 5; +const KEY_NUMLOCK: u8 = 1 << 6; +const KEY_COUNT_MASK: u8 = 0x1F; // 0x1F == 31 -#[embassy_executor::task] -pub async fn keyboard( - mut i2c: I2c<'static, I2C1, Async>, - channel: Sender<'static, NoopRawMutex, KeyEvent, 10>, +pub async fn read_keyboard_fifo( + i2c: &mut I2c<'static, I2C1, Async>, + channel: &mut Sender<'static, NoopRawMutex, KeyEvent, 10>, ) { - embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await; + let mut key_status = [0_u8; 1]; - let mut res = [0_u8; 2]; - if i2c.read_async(KEYBOARD_ADDR, &mut res).await.is_ok() { - if let Ok(state) = KeyState::try_from(res[0]) { - if let Ok(key) = KeyCode::try_from(res[1]) { - let _ = channel.try_send(KeyEvent { key, state }); + if i2c + .write_read_async(super::MCU_ADDR, [REG_ID_KEY], &mut key_status) + .await + .is_ok() + { + // TODO: use caps & num lock + let caps = key_status[0] & KEY_CAPSLOCK == KEY_CAPSLOCK; + let num = key_status[0] & KEY_NUMLOCK == KEY_NUMLOCK; + let fifo_count = key_status[0] & KEY_COUNT_MASK; + + if fifo_count >= 1 { + let mut event = [0_u8; 2]; + + if i2c + .write_read_async(super::MCU_ADDR, [REG_ID_FIF], &mut event) + .await + .is_ok() + { + if let Ok(state) = KeyState::try_from(event[0]) { + if let Ok(key) = KeyCode::try_from(event[1]) { + let _ = channel.try_send(KeyEvent { key, state }); + } + } } } } } +pub struct KeyEvent { + pub key: KeyCode, + pub state: KeyState, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum KeyState { Idle = 0, diff --git a/src/peripherals/mod.rs b/src/peripherals/mod.rs new file mode 100644 index 0000000..d0537c6 --- /dev/null +++ b/src/peripherals/mod.rs @@ -0,0 +1,56 @@ +/// handles polling keyboard events and battery levels from mcu over i2c1 +/// +use embassy_rp::{ + i2c::{Async, I2c}, + peripherals::I2C1, +}; +use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Sender}; +use embassy_time::Timer; + +#[cfg(feature = "defmt")] +use defmt::info; + +pub mod keyboard; +use keyboard::{KeyCode, KeyEvent, KeyState}; +mod battery; +pub use battery::BATTERY_PCT; +use battery::read_battery; + +use crate::peripherals::keyboard::read_keyboard_fifo; + +const MCU_ADDR: u8 = 0x1F; + +const REG_ID_VER: u8 = 0x01; +const REG_ID_CFG: u8 = 0x02; +const REG_ID_INT: u8 = 0x03; +const REG_ID_KEY: u8 = 0x04; +const REG_ID_BKL: u8 = 0x05; +const REG_ID_DEB: u8 = 0x06; +const REG_ID_FRQ: u8 = 0x07; +const REG_ID_RST: u8 = 0x08; +const REG_ID_FIF: u8 = 0x09; +const REG_ID_BK2: u8 = 0x0A; +const REG_ID_C64_MTX: u8 = 0x0c; +const REG_ID_C64_JS: u8 = 0x0d; + +#[embassy_executor::task] +pub async fn peripherals_task( + mut i2c: I2c<'static, I2C1, Async>, + mut keyboard_channel: Sender<'static, NoopRawMutex, KeyEvent, 10>, +) { + Timer::after(embassy_time::Duration::from_millis(100)).await; + + #[cfg(feature = "defmt")] + { + let mut ver = [0_u8; 1]; + if let Ok(firm_ver) = i2c.write_read_async(MCU_ADDR, [REG_ID_VER], &mut ver).await { + info!("stm32 firmware version: v{}", ver[0]); + } + } + + loop { + read_battery(&mut i2c).await; + + read_keyboard_fifo(&mut i2c, &mut keyboard_channel).await; + } +}