Added sticky key support
This commit is contained in:
parent
60309e3c7a
commit
e332b0dc5e
@ -161,11 +161,15 @@ fn main() -> ! {
|
|||||||
let mut status_led_count_down = timer.count_down();
|
let mut status_led_count_down = timer.count_down();
|
||||||
status_led_count_down.start(250.millis());
|
status_led_count_down.start(250.millis());
|
||||||
|
|
||||||
|
let mut start_count_down = timer.count_down();
|
||||||
|
start_count_down.start(5000.millis());
|
||||||
|
|
||||||
// Create variables to track caps lock and fn mode
|
// Create variables to track caps lock and fn mode
|
||||||
let mut caps_lock_active: bool = false;
|
let mut caps_lock_active: bool = false;
|
||||||
let mut fn_mode: u8;
|
let mut fn_mode: u8;
|
||||||
let mut gui_lock_state: u8 = 0;
|
let mut sticky_state: u8 = 0;
|
||||||
let mut gui_lock_trigger_index: u8 = 0;
|
let mut sticky_key: Keyboard = Keyboard::NoEventIndicated;
|
||||||
|
let mut started: bool = false;
|
||||||
|
|
||||||
// Initialize button matrix
|
// Initialize button matrix
|
||||||
button_matrix.init_pins();
|
button_matrix.init_pins();
|
||||||
@ -185,7 +189,11 @@ fn main() -> ! {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
if status_led_count_down.wait().is_ok() {
|
if status_led_count_down.wait().is_ok() {
|
||||||
update_status_led(&mut status_led, &caps_lock_active, &gui_lock_state);
|
update_status_led(&mut status_led, &caps_lock_active, &sticky_state, &started);
|
||||||
|
}
|
||||||
|
|
||||||
|
if start_count_down.wait().is_ok() && !started {
|
||||||
|
started = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if usb_hid_report_count_down.wait().is_ok() {
|
if usb_hid_report_count_down.wait().is_ok() {
|
||||||
@ -193,19 +201,16 @@ fn main() -> ! {
|
|||||||
|
|
||||||
fn_mode = get_fn_mode(pressed_keys);
|
fn_mode = get_fn_mode(pressed_keys);
|
||||||
|
|
||||||
if !caps_lock_active {
|
if !caps_lock_active && sticky_state != 2 {
|
||||||
update_status_led(&mut status_led, &caps_lock_active, &gui_lock_state);
|
update_status_led(&mut status_led, &caps_lock_active, &sticky_state, &started);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, key) in pressed_keys.iter().enumerate() {
|
for (index, key) in pressed_keys.iter().enumerate() {
|
||||||
buttons[index].pressed = *key;
|
buttons[index].pressed = *key;
|
||||||
}
|
}
|
||||||
|
|
||||||
let keyboard_report = get_keyboard_report(
|
let keyboard_report =
|
||||||
&mut buttons,
|
get_keyboard_report(&mut buttons, fn_mode, &mut sticky_state, &mut sticky_key);
|
||||||
fn_mode,
|
|
||||||
&mut gui_lock_state,
|
|
||||||
&mut gui_lock_trigger_index,
|
|
||||||
);
|
|
||||||
|
|
||||||
match keyboard.device().write_report(keyboard_report) {
|
match keyboard.device().write_report(keyboard_report) {
|
||||||
Err(UsbHidError::WouldBlock) => {}
|
Err(UsbHidError::WouldBlock) => {}
|
||||||
@ -248,8 +253,8 @@ fn main() -> ! {
|
|||||||
|
|
||||||
/// Update status LED colour based on function layer and capslock
|
/// Update status LED colour based on function layer and capslock
|
||||||
///
|
///
|
||||||
/// Normal = green (NORMAL)
|
/// Normal = Off (OFF)
|
||||||
/// GUI lock = blue (GUI LOCK)
|
/// STICKY lock = blue/falshing blue (ACTIVITY)
|
||||||
/// Capslock active = flashing red (WARNING)
|
/// Capslock active = flashing red (WARNING)
|
||||||
/// Error = steady red (ERROR)
|
/// Error = steady red (ERROR)
|
||||||
///
|
///
|
||||||
@ -259,7 +264,8 @@ fn main() -> ! {
|
|||||||
fn update_status_led<P, SM, I>(
|
fn update_status_led<P, SM, I>(
|
||||||
status_led: &mut Ws2812StatusLed<P, SM, I>,
|
status_led: &mut Ws2812StatusLed<P, SM, I>,
|
||||||
caps_lock_active: &bool,
|
caps_lock_active: &bool,
|
||||||
gui_lock_state: &u8,
|
sticky_state: &u8,
|
||||||
|
started: &bool,
|
||||||
) where
|
) where
|
||||||
P: PIOExt + FunctionConfig,
|
P: PIOExt + FunctionConfig,
|
||||||
I: PinId,
|
I: PinId,
|
||||||
@ -268,10 +274,14 @@ fn update_status_led<P, SM, I>(
|
|||||||
{
|
{
|
||||||
if *caps_lock_active {
|
if *caps_lock_active {
|
||||||
status_led.update(StatusMode::Warning);
|
status_led.update(StatusMode::Warning);
|
||||||
} else if *gui_lock_state != 0 {
|
} else if *sticky_state == 1 {
|
||||||
status_led.update(StatusMode::Activity);
|
status_led.update(StatusMode::Activity);
|
||||||
} else {
|
} else if *sticky_state == 2 {
|
||||||
|
status_led.update(StatusMode::ActivityFlash);
|
||||||
|
} else if !(*started) {
|
||||||
status_led.update(StatusMode::Normal);
|
status_led.update(StatusMode::Normal);
|
||||||
|
} else {
|
||||||
|
status_led.update(StatusMode::Off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,27 +312,37 @@ fn get_fn_mode(pressed_keys: [bool; NUMBER_OF_KEYS]) -> u8 {
|
|||||||
///
|
///
|
||||||
/// * `matrix_keys` - Array of pressed keys
|
/// * `matrix_keys` - Array of pressed keys
|
||||||
/// * `fn_mode` - Current function layer
|
/// * `fn_mode` - Current function layer
|
||||||
/// * `gui_lock` - Is GUI lock active
|
/// * `sticky_state` - Is STICKY lock active
|
||||||
/// * `gui_lock_index` - Index of the key pressed after GUI lock was activated
|
/// * `sticky_key` - the key pressed after STICKY lock was activated
|
||||||
fn get_keyboard_report(
|
fn get_keyboard_report(
|
||||||
matrix_keys: &mut [KeyboardButton; NUMBER_OF_KEYS],
|
matrix_keys: &mut [KeyboardButton; NUMBER_OF_KEYS],
|
||||||
fn_mode: u8,
|
fn_mode: u8,
|
||||||
gui_lock_state: &mut u8,
|
sticky_state: &mut u8,
|
||||||
gui_lock_trigger_index: &mut u8,
|
sticky_key: &mut Keyboard,
|
||||||
) -> [Keyboard; NUMBER_OF_KEYS] {
|
) -> [Keyboard; NUMBER_OF_KEYS] {
|
||||||
let mut keyboard_report: [Keyboard; NUMBER_OF_KEYS] =
|
let mut keyboard_report: [Keyboard; NUMBER_OF_KEYS] =
|
||||||
[Keyboard::NoEventIndicated; NUMBER_OF_KEYS];
|
[Keyboard::NoEventIndicated; NUMBER_OF_KEYS];
|
||||||
|
|
||||||
// Filter report based on Fn mode and pressed keys
|
// Filter report based on Fn mode and pressed keys
|
||||||
for (index, key) in matrix_keys.iter_mut().enumerate() {
|
for (index, key) in matrix_keys.iter_mut().enumerate() {
|
||||||
// Check if GUI lock button is pressed
|
// Check if STICKY button is pressed (SET STICKY)
|
||||||
if key.pressed != key.previous_pressed
|
if key.pressed != key.previous_pressed
|
||||||
&& key.pressed
|
&& key.pressed
|
||||||
&& index as u8 == layout::GUI_LOCK_BUTTON[0]
|
&& index as u8 == layout::STICKY_BUTTON[0]
|
||||||
&& fn_mode == layout::GUI_LOCK_BUTTON[1]
|
&& fn_mode == layout::STICKY_BUTTON[1]
|
||||||
&& *gui_lock_state == 0
|
&& *sticky_state == 0
|
||||||
{
|
{
|
||||||
*gui_lock_state = 1;
|
*sticky_state = 1;
|
||||||
|
}
|
||||||
|
// Check if STICKY button is pressed (CLEAR STICKY)
|
||||||
|
else if key.pressed != key.previous_pressed
|
||||||
|
&& key.pressed
|
||||||
|
&& index as u8 == layout::STICKY_BUTTON[0]
|
||||||
|
&& fn_mode == layout::STICKY_BUTTON[1]
|
||||||
|
&& *sticky_state != 0
|
||||||
|
{
|
||||||
|
*sticky_state = 0;
|
||||||
|
*sticky_key = Keyboard::NoEventIndicated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set fn mode for the pressed button
|
// Set fn mode for the pressed button
|
||||||
@ -336,22 +356,11 @@ fn get_keyboard_report(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Index of GUI key in keyboard report
|
// If STICKY lock is active, hold index key pressed until STICKY lock key is pressed
|
||||||
/// Index 36, 37, 38, 45, 46, 47 are not used by any other keys
|
// again
|
||||||
const GUI_REPORT_INDEX: usize = 47;
|
if *sticky_state == 1 && key.pressed {
|
||||||
|
*sticky_key = layout::MAP[key.fn_mode as usize][index];
|
||||||
// If GUI lock is active, set LeftGUI key to pressed
|
*sticky_state = 2;
|
||||||
// when next button is pressed. Keep LeftGUI pressed
|
|
||||||
// until next button is released
|
|
||||||
if *gui_lock_state == 1 && key.pressed {
|
|
||||||
*gui_lock_trigger_index = index as u8;
|
|
||||||
*gui_lock_state = 2;
|
|
||||||
keyboard_report[GUI_REPORT_INDEX] = Keyboard::LeftGUI;
|
|
||||||
} else if *gui_lock_state == 2 && *gui_lock_trigger_index == index as u8 && key.pressed {
|
|
||||||
keyboard_report[GUI_REPORT_INDEX] = Keyboard::LeftGUI;
|
|
||||||
*gui_lock_state = 3;
|
|
||||||
} else if *gui_lock_state == 3 && *gui_lock_trigger_index == index as u8 && !key.pressed {
|
|
||||||
*gui_lock_state = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add defined HID key to the report
|
// Add defined HID key to the report
|
||||||
@ -359,5 +368,12 @@ fn get_keyboard_report(
|
|||||||
keyboard_report[index] = layout::MAP[key.fn_mode as usize][index];
|
keyboard_report[index] = layout::MAP[key.fn_mode as usize][index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Index of STICKY key in keyboard report
|
||||||
|
/// Index 36, 37, 38, 45, 46, 47 are not used by any other keys
|
||||||
|
const STICKY_REPORT_INDEX: usize = 46;
|
||||||
|
// Add sticky key to the report
|
||||||
|
keyboard_report[STICKY_REPORT_INDEX] = *sticky_key;
|
||||||
|
|
||||||
keyboard_report
|
keyboard_report
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,10 +26,12 @@ pub enum StatusMode {
|
|||||||
Off = 0,
|
Off = 0,
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
Activity = 2,
|
Activity = 2,
|
||||||
Other = 3,
|
ActivityFlash = 3,
|
||||||
Warning = 4,
|
Other = 4,
|
||||||
Error = 5,
|
OtherFlash = 5,
|
||||||
Bootloader = 6,
|
Warning = 6,
|
||||||
|
Error = 7,
|
||||||
|
Bootloader = 8,
|
||||||
}
|
}
|
||||||
#[warn(dead_code)]
|
#[warn(dead_code)]
|
||||||
|
|
||||||
@ -100,22 +102,32 @@ where
|
|||||||
///
|
///
|
||||||
/// Make sure to call this function regularly to keep the LED flashing
|
/// Make sure to call this function regularly to keep the LED flashing
|
||||||
pub fn update(&mut self, mode: StatusMode) {
|
pub fn update(&mut self, mode: StatusMode) {
|
||||||
let colors: [RGB8; 7] = [
|
let colors: [RGB8; 9] = [
|
||||||
(0, 0, 0).into(), // Off
|
(0, 0, 0).into(), // Off
|
||||||
(10, 7, 0).into(), // Green
|
(10, 7, 0).into(), // Green
|
||||||
(10, 4, 10).into(), // Blue
|
(10, 4, 10).into(), // Blue
|
||||||
|
(10, 4, 10).into(), // Blue
|
||||||
|
(5, 10, 0).into(), // Orange
|
||||||
(5, 10, 0).into(), // Orange
|
(5, 10, 0).into(), // Orange
|
||||||
(2, 20, 0).into(), // Red
|
(2, 20, 0).into(), // Red
|
||||||
(2, 20, 0).into(), // Red
|
(2, 20, 0).into(), // Red
|
||||||
(0, 10, 10).into(), // Purple
|
(0, 10, 10).into(), // Purple
|
||||||
];
|
];
|
||||||
|
|
||||||
if mode == StatusMode::Warning && !self.state {
|
if (mode == StatusMode::ActivityFlash
|
||||||
|
|| mode == StatusMode::OtherFlash
|
||||||
|
|| mode == StatusMode::Warning)
|
||||||
|
&& !self.state
|
||||||
|
{
|
||||||
self.ws2812_direct
|
self.ws2812_direct
|
||||||
.write([colors[mode as usize]].iter().copied())
|
.write([colors[mode as usize]].iter().copied())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.state = true;
|
self.state = true;
|
||||||
} else if mode == StatusMode::Warning || mode == StatusMode::Off {
|
} else if mode == StatusMode::ActivityFlash
|
||||||
|
|| mode == StatusMode::OtherFlash
|
||||||
|
|| mode == StatusMode::Warning
|
||||||
|
|| mode == StatusMode::Off
|
||||||
|
{
|
||||||
self.ws2812_direct
|
self.ws2812_direct
|
||||||
.write([colors[0]].iter().copied())
|
.write([colors[0]].iter().copied())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user