Merge pull request #5 from nicholasmello/multikey
Some checks are pending
Rust CI / Check (push) Waiting to run
Rust CI / Clippy (push) Waiting to run
Rust CI / Format (push) Waiting to run
Rust CI / Build (push) Blocked by required conditions
Rust CI / Documentation (push) Waiting to run
Rust CI / Deploy Docs (push) Blocked by required conditions

Multikey support
This commit is contained in:
2026-07-25 16:23:34 -05:00
committed by GitHub
3 changed files with 56 additions and 94 deletions

View File

@@ -1,4 +1,4 @@
use crate::usb::KeyboardEvent;
use alloc::vec::Vec;
use embassy_rp::gpio::Input;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::channel::Sender;
@@ -46,7 +46,7 @@ impl<'d, const KEY_N: usize> Keyboard<'d, KEY_N> {
Ok(())
}
pub async fn process<'ch, M, const N: usize>(mut self, sender: Sender<'ch, M, KeyboardEvent, N>)
pub async fn process<'ch, M, const N: usize>(mut self, sender: Sender<'ch, M, Vec<char>, N>)
where
M: RawMutex,
{
@@ -57,14 +57,14 @@ impl<'d, const KEY_N: usize> Keyboard<'d, KEY_N> {
.collect::<FuturesUnordered<_>>()
.next()
.await;
let mut pressed: Vec<char> = Vec::new();
for key in self.keys.iter_mut().filter_map(|opt| opt.as_mut()) {
sender
.send(KeyboardEvent {
key: key.value,
action: key.button.get_level().into(),
})
.await;
if key.button.is_low() {
pressed.push(key.value);
}
}
sender.send(pressed).await;
}
}
}

View File

@@ -5,8 +5,10 @@ mod heartbeat;
mod keyboard;
mod usb;
extern crate alloc;
use crate::heartbeat::heartbeat;
use crate::keyboard::Keyboard;
use alloc::vec::Vec;
use defmt::*;
use embassy_executor::Spawner;
use embassy_futures::join::join;
@@ -37,7 +39,7 @@ async fn main(_spawner: Spawner) {
);
}
let keyboard_events: Channel<ThreadModeRawMutex, usb::KeyboardEvent, 64> = Channel::new();
let keyboard_events: Channel<ThreadModeRawMutex, Vec<char>, 64> = Channel::new();
let p = embassy_rp::init(Default::default());
@@ -57,40 +59,40 @@ async fn main(_spawner: Spawner) {
}
let mut signal_pin = Input::new(p.PIN_16, Pull::None);
signal_pin.set_schmitt(true);
match keyboard.add_key(signal_pin, 'a') {
Ok(()) => info!("Key 'a' registered"),
match keyboard.add_key(signal_pin, 's') {
Ok(()) => info!("Key 's' registered"),
Err(e) => {
defmt::panic!("Failed to register key! {:?}", e);
}
}
let mut signal_pin = Input::new(p.PIN_17, Pull::None);
signal_pin.set_schmitt(true);
match keyboard.add_key(signal_pin, 'a') {
Ok(()) => info!("Key 'a' registered"),
match keyboard.add_key(signal_pin, 'x') {
Ok(()) => info!("Key 'x' registered"),
Err(e) => {
defmt::panic!("Failed to register key! {:?}", e);
}
}
let mut signal_pin = Input::new(p.PIN_18, Pull::None);
signal_pin.set_schmitt(true);
match keyboard.add_key(signal_pin, 'a') {
Ok(()) => info!("Key 'a' registered"),
match keyboard.add_key(signal_pin, 'd') {
Ok(()) => info!("Key 'd' registered"),
Err(e) => {
defmt::panic!("Failed to register key! {:?}", e);
}
}
let mut signal_pin = Input::new(p.PIN_19, Pull::None);
signal_pin.set_schmitt(true);
match keyboard.add_key(signal_pin, 'a') {
Ok(()) => info!("Key 'a' registered"),
match keyboard.add_key(signal_pin, 'c') {
Ok(()) => info!("Key 'c' registered"),
Err(e) => {
defmt::panic!("Failed to register key! {:?}", e);
}
}
let mut signal_pin = Input::new(p.PIN_20, Pull::None);
signal_pin.set_schmitt(true);
match keyboard.add_key(signal_pin, 'a') {
Ok(()) => info!("Key 'a' registered"),
match keyboard.add_key(signal_pin, 'w') {
Ok(()) => info!("Key 'w' registered"),
Err(e) => {
defmt::panic!("Failed to register key! {:?}", e);
}

View File

@@ -1,8 +1,8 @@
use alloc::vec::Vec;
use core::cell::OnceCell;
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use defmt::*;
use embassy_futures::join::join;
use embassy_rp::gpio::Level;
use embassy_rp::peripherals::USB;
use embassy_rp::usb::Driver;
use embassy_sync::blocking_mutex::raw::RawMutex;
@@ -18,27 +18,6 @@ use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
pub static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
#[derive(Clone, Copy)]
pub enum KeyboardAction {
Press,
Depress,
}
impl From<Level> for KeyboardAction {
fn from(value: Level) -> Self {
match value {
Level::High => KeyboardAction::Depress,
Level::Low => KeyboardAction::Press,
}
}
}
#[derive(Clone, Copy)]
pub struct KeyboardEvent {
pub key: char,
pub action: KeyboardAction,
}
pub struct UsbKeyboardBuf<'d> {
// Create embassy-usb DeviceBuilder using the driver and config.
// It needs some buffers for building the descriptors.
@@ -128,7 +107,7 @@ impl<'d> UsbKeyboard<'d> {
}
}
pub async fn run<'ch, M, const N: usize>(self, receiver: Receiver<'ch, M, KeyboardEvent, N>)
pub async fn run<'ch, M, const N: usize>(self, receiver: Receiver<'ch, M, Vec<char>, N>)
where
M: RawMutex,
{
@@ -148,58 +127,39 @@ impl<'d> UsbKeyboard<'d> {
loop {
let event = receiver.receive().await;
match event {
KeyboardEvent {
key: 'a',
action: KeyboardAction::Press,
} => {
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8
{
match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
let mut boot_keys = [0, 0, 0, 0, 0, 0, 0, 0];
for (&key, idx) in event.iter().zip(2usize..) {
let boot_key = match key {
'd' => 79,
'a' => 80,
's' => 81,
'w' => 82,
('a'..='z') => (key as u8) - b'a' + 4,
_ => defmt::panic!("Not supported key: {}", key),
};
boot_keys[idx] = boot_key;
}
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
match writer.write(&boot_keys).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),
};
}
}
KeyboardEvent {
key: 'a',
action: KeyboardAction::Depress,
} => {
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),
};
}
}
_ => {
defmt::panic!("Unexpected event!");
}
defmt::unimplemented!("Only supports boot mode keyboards!");
// // 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),
// };
}
}
};