Implement modifiers and modtap

This commit is contained in:
2023-03-19 22:18:08 +01:00
parent 05e5cbc917
commit a444b8c61e
4 changed files with 147 additions and 113 deletions

View File

@ -97,24 +97,25 @@ async fn switch_task(switch_num: usize, pin: AnyPin, layers: &'static [Layer]) -
KB_REPORT.lock().await.release_key(key);
continue;
}
Button::Mod(modifier) => {
// TODO
//KB_REPORT.lock().await.press_mod(modifier);
//pin.wait_for_high().await;
//KB_REPORT.lock().await.release_mod(modifier);
//continue;
&Button::Mod(modifier) => {
KB_REPORT.lock().await.press_modifier(modifier);
wait_for_release.await;
KB_REPORT.lock().await.release_modifier(modifier);
continue;
}
Button::ModTap { keycode, modifier } => {
&Button::ModTap { keycode, modifier } => {
select_biased! {
_ = Timer::after(MOD_TAP_TIME).fuse() => {
// TODO: Modifier
KB_REPORT.lock().await.press_modifier(modifier);
pin.wait_for_high().await;
KB_REPORT.lock().await.release_modifier(modifier);
debug!("switch {switch_num} button {button:?} released");
continue;
}
_ = wait_for_release.fuse() => {
KB_REPORT.lock().await.press_key(*keycode);
KB_REPORT.lock().await.press_key(keycode);
Timer::after(Duration::from_millis(10)).await;
KB_REPORT.lock().await.release_key(*keycode);
KB_REPORT.lock().await.release_key(keycode);
continue;
}
}
@ -122,10 +123,12 @@ async fn switch_task(switch_num: usize, pin: AnyPin, layers: &'static [Layer]) -
Button::NextLayer => {
let next_layer = (current_layer + 1) % layer_count;
CURRENT_LAYER.store(next_layer, Ordering::Relaxed);
debug!("switched to layer {next_layer}");
}
Button::PrevLayer => {
let prev_layer = current_layer.checked_sub(1).unwrap_or(layer_count - 1);
CURRENT_LAYER.store(prev_layer, Ordering::Relaxed);
debug!("switched to layer {prev_layer}");
}
Button::None => {}
}

View File

@ -103,7 +103,7 @@ async fn keyboard_test(mut stream: HidStream, _handler: &'static Handler) -> Res
}
#[cfg(feature = "n-key-rollover")]
stream.write(&report.serialized()).await?;
stream.write(report.as_bytes()).await?;
#[cfg(not(feature = "n-key-rollover"))]
stream.write_serialize(&report).await?;

View File

@ -7,21 +7,24 @@
/// Unlike usbd_hids KeyboardReport, this one supports N-key rollover.
#[derive(Clone, PartialEq, Eq)]
#[cfg(feature = "n-key-rollover")]
#[repr(C, packed)]
pub struct KeyboardReport {
pub modifier: u8,
/// Bitmap representing all keycodes from 0 to 104
pub keycodes: [u8; 13],
/// Bitmap representing all keycodes from 0 to 215
pub keycodes: [u8; 27],
}
use tgnt::keys::Key;
use core::mem::{size_of, transmute};
use tgnt::{button::Modifier, keys::Key};
#[cfg(not(feature = "n-key-rollover"))]
pub use usbd_hid::descriptor::KeyboardReport;
pub use ::usbd_hid::descriptor::KeyboardReport;
#[cfg(feature = "n-key-rollover")]
pub const EMPTY_KEYBOARD_REPORT: KeyboardReport = KeyboardReport {
modifier: 0,
keycodes: [0; 13],
keycodes: [0; 27],
};
#[cfg(not(feature = "n-key-rollover"))]
@ -34,6 +37,7 @@ pub const EMPTY_KEYBOARD_REPORT: KeyboardReport = KeyboardReport {
#[cfg(feature = "n-key-rollover")]
impl KeyboardReport {
#[inline(always)]
pub fn set_key(&mut self, key: Key, pressed: bool) {
let keycode = u8::from(key);
let byte = keycode >> 3;
@ -51,29 +55,43 @@ impl KeyboardReport {
}
}
#[inline(always)]
pub fn press_key(&mut self, key: Key) {
self.set_key(key, true)
}
#[inline(always)]
pub fn release_key(&mut self, key: Key) {
self.set_key(key, false)
}
pub fn serialized(&self) -> [u8; 14] {
let [a, b, c, d, e, f, g, h, i, j, k, l, m] = self.keycodes;
[self.modifier, a, b, c, d, e, f, g, h, i, j, k, l, m]
#[inline(always)]
pub fn set_modifier(&mut self, modifier: Modifier, pressed: bool) {
if pressed {
self.modifier |= u8::from(modifier);
} else {
self.modifier &= !u8::from(modifier);
}
}
#[inline(always)]
pub fn press_modifier(&mut self, modifier: Modifier) {
self.set_modifier(modifier, true)
}
#[inline(always)]
pub fn release_modifier(&mut self, modifier: Modifier) {
self.set_modifier(modifier, false)
}
#[inline(always)]
pub fn as_bytes(&self) -> &[u8; size_of::<KeyboardReport>()] {
// SAFETY: KeyboardReport is repr(C, packed) and contains only u8s.
unsafe { transmute(self) }
}
}
// bitmasks for the `modifier` field
pub const MOD_LCTRL: u8 = 0x01;
pub const MOD_LSHIFT: u8 = 0x02;
pub const MOD_LALT: u8 = 0x04;
pub const MOD_LSUPER: u8 = 0x08;
pub const MOD_RCTRL: u8 = 0x10;
pub const MOD_RSHIFT: u8 = 0x20;
pub const MOD_RALT: u8 = 0x40;
pub const MOD_RSUPER: u8 = 0x80;
#[cfg(feature = "n-key-rollover")]
impl usbd_hid::descriptor::SerializedDescriptor for KeyboardReport {
@ -95,8 +113,10 @@ impl usbd_hid::descriptor::SerializedDescriptor for KeyboardReport {
0x81, 0x02, // input (variable)
//
0x19, 0x00, // local usage minimum
0x29, 0x67, // local usage maximum
0x95, 0x68, // report count
//0x29, 0x67, // local usage maximum (0x67)
//0x95, 0x68, // report count (0x68)
0x29, 215, // local usage maximum (215)
0x95, 216, // report count (216)
0x81, 0x02, // input (variable)
//
0x05, 0x08, // usage page 8 (led page)