keyboard: Move keyboard logic
Signed-off-by: Nicholas Mello <nick@nmello.dev>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -33,6 +33,7 @@ dependencies = [
|
||||
"embassy-executor",
|
||||
"embassy-futures",
|
||||
"embassy-rp",
|
||||
"embassy-sync",
|
||||
"embassy-time",
|
||||
"embassy-usb",
|
||||
"panic-probe",
|
||||
@@ -514,6 +515,7 @@ checksum = "7bbd85cf5a5ae56bdf26f618364af642d1d0a4e245cdd75cd9aabda382f65a81"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"defmt 1.1.1",
|
||||
"embedded-io-async 0.7.0",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
|
||||
@@ -10,6 +10,7 @@ defmt-rtt = "1.3.0"
|
||||
embassy-executor = { version = "0.10.0", features = ["executor-thread", "platform-cortex-m"] }
|
||||
embassy-futures = { version = "0.1.2", features = ["defmt"] }
|
||||
embassy-rp = { version = "0.10.0", features = ["chrono", "defmt", "rp2040", "rt", "time-driver", "critical-section-impl"] }
|
||||
embassy-sync = { version = "0.8.0", features = ["defmt"] }
|
||||
embassy-time = "0.5.1"
|
||||
embassy-usb = { version = "0.6.0", features = ["defmt"] }
|
||||
panic-probe = { version = "1.0.0", features = ["defmt"] }
|
||||
|
||||
123
src/keyboard.rs
Normal file
123
src/keyboard.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use defmt::*;
|
||||
use embassy_rp::gpio::Input;
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_usb::{
|
||||
class::hid::{HidProtocolMode, HidWriter},
|
||||
driver::Driver,
|
||||
};
|
||||
use usbd_hid::descriptor::KeyboardReport;
|
||||
|
||||
use crate::HID_PROTOCOL_MODE;
|
||||
|
||||
const WRITE_N: usize = 8;
|
||||
|
||||
pub struct Key<'a> {
|
||||
button: Input<'a>,
|
||||
value: char,
|
||||
}
|
||||
|
||||
impl Key<'_> {
|
||||
pub async fn process<'d, D: Driver<'d>>(
|
||||
&mut self,
|
||||
mut writer: Mutex<CriticalSectionRawMutex, HidWriter<'d, D, WRITE_N>>,
|
||||
) {
|
||||
loop {
|
||||
self.button.wait_for_high().await;
|
||||
info!("Button {} pressed", self.value);
|
||||
|
||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
||||
match writer.get_mut().write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||
};
|
||||
} else {
|
||||
// Create a report with the A key pressed. (no shift modifier)
|
||||
let report = KeyboardReport {
|
||||
keycodes: [4, 0, 0, 0, 0, 0],
|
||||
leds: 0,
|
||||
modifier: 0,
|
||||
reserved: 0,
|
||||
};
|
||||
// Send the report.
|
||||
match writer.get_mut().write_serialize(&report).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||
};
|
||||
}
|
||||
|
||||
// Debounce
|
||||
Timer::after(Duration::from_millis(50)).await;
|
||||
|
||||
self.button.wait_for_low().await;
|
||||
info!("Button {} unpressed", self.value);
|
||||
|
||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
||||
match writer.get_mut().write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||
};
|
||||
} else {
|
||||
let report = KeyboardReport {
|
||||
keycodes: [0, 0, 0, 0, 0, 0],
|
||||
leds: 0,
|
||||
modifier: 0,
|
||||
reserved: 0,
|
||||
};
|
||||
match writer.get_mut().write_serialize(&report).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||
};
|
||||
}
|
||||
|
||||
// Debounce
|
||||
Timer::after(Duration::from_millis(50)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Key<'_> {
|
||||
#[allow(unused)]
|
||||
pub async fn set_value(mut self, value: char) {
|
||||
self.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Keyboard<'d, D: Driver<'d>, const KEY_N: usize> {
|
||||
writer: Mutex<CriticalSectionRawMutex, HidWriter<'d, D, WRITE_N>>,
|
||||
keys: [Option<Key<'d>>; KEY_N],
|
||||
num_keys: usize,
|
||||
}
|
||||
|
||||
pub enum KeyboardError {
|
||||
MaxKeys,
|
||||
}
|
||||
|
||||
impl<'d, D: Driver<'d>, const KEY_N: usize> Keyboard<'d, D, KEY_N> {
|
||||
pub fn new(writer: HidWriter<'d, D, WRITE_N>) -> Self {
|
||||
Self {
|
||||
writer: Mutex::new(writer),
|
||||
keys: [const { None }; KEY_N],
|
||||
num_keys: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_key(&mut self, button: Input<'d>, value: char) -> Result<(), KeyboardError> {
|
||||
let key = self
|
||||
.keys
|
||||
.get_mut(self.num_keys)
|
||||
.ok_or(KeyboardError::MaxKeys)?;
|
||||
*key = Some(Key { button, value });
|
||||
|
||||
self.num_keys += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn process(mut self) {
|
||||
// TODO: Make this a loop that is concatinated together
|
||||
self.keys[0].as_mut().unwrap().process(self.writer).await;
|
||||
}
|
||||
}
|
||||
63
src/main.rs
63
src/main.rs
@@ -2,9 +2,11 @@
|
||||
#![no_main]
|
||||
|
||||
mod heartbeat;
|
||||
mod keyboard;
|
||||
|
||||
use crate::heartbeat::heartbeat;
|
||||
use crate::keyboard::Keyboard;
|
||||
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
@@ -18,6 +20,7 @@ use embassy_usb::class::hid::{
|
||||
use embassy_usb::control::OutResponse;
|
||||
use embassy_usb::{Builder, Config, Handler};
|
||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
||||
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
@@ -84,55 +87,15 @@ async fn main(_spawner: Spawner) {
|
||||
// Enable the schmitt trigger to slightly debounce.
|
||||
signal_pin.set_schmitt(true);
|
||||
|
||||
let (reader, mut writer) = hid.split();
|
||||
let (reader, writer) = hid.split();
|
||||
|
||||
// Do stuff with the class!
|
||||
let in_fut = async {
|
||||
loop {
|
||||
signal_pin.wait_for_high().await;
|
||||
info!("HIGH DETECTED");
|
||||
|
||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
||||
match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||
};
|
||||
} else {
|
||||
// Create a report with the A key pressed. (no shift modifier)
|
||||
let report = KeyboardReport {
|
||||
keycodes: [4, 0, 0, 0, 0, 0],
|
||||
leds: 0,
|
||||
modifier: 0,
|
||||
reserved: 0,
|
||||
};
|
||||
// Send the report.
|
||||
match writer.write_serialize(&report).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||
};
|
||||
}
|
||||
|
||||
signal_pin.wait_for_low().await;
|
||||
info!("LOW DETECTED");
|
||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
||||
match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||
};
|
||||
} else {
|
||||
let report = KeyboardReport {
|
||||
keycodes: [0, 0, 0, 0, 0, 0],
|
||||
leds: 0,
|
||||
modifier: 0,
|
||||
reserved: 0,
|
||||
};
|
||||
match writer.write_serialize(&report).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||
};
|
||||
}
|
||||
let mut keyboard = Keyboard::<_, 1>::new(writer);
|
||||
match keyboard.add_key(signal_pin, 'a') {
|
||||
Ok(()) => info!("Key 'a' registered"),
|
||||
Err(_) => {
|
||||
defmt::panic!("Failed to register key!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let out_fut = async {
|
||||
reader.run(false, &mut request_handler).await;
|
||||
@@ -142,8 +105,8 @@ async fn main(_spawner: Spawner) {
|
||||
let led = Output::new(p.PIN_25, Level::Low);
|
||||
|
||||
join(
|
||||
join(usb.run(), heartbeat::heartbeat(led)),
|
||||
join(in_fut, out_fut),
|
||||
join(usb.run(), heartbeat(led)),
|
||||
join(keyboard.process(), out_fut),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user