diff --git a/rp2040/src/main.rs b/rp2040/src/main.rs index 1df1cac..ee3854f 100644 --- a/rp2040/src/main.rs +++ b/rp2040/src/main.rs @@ -161,11 +161,15 @@ fn main() -> ! { let mut status_led_count_down = timer.count_down(); 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 let mut caps_lock_active: bool = false; let mut fn_mode: u8; - let mut gui_lock_state: u8 = 0; - let mut gui_lock_trigger_index: u8 = 0; + let mut sticky_state: u8 = 0; + let mut sticky_key: Keyboard = Keyboard::NoEventIndicated; + let mut started: bool = false; // Initialize button matrix button_matrix.init_pins(); @@ -185,7 +189,11 @@ fn main() -> ! { loop { 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() { @@ -193,19 +201,16 @@ fn main() -> ! { fn_mode = get_fn_mode(pressed_keys); - if !caps_lock_active { - update_status_led(&mut status_led, &caps_lock_active, &gui_lock_state); + if !caps_lock_active && sticky_state != 2 { + update_status_led(&mut status_led, &caps_lock_active, &sticky_state, &started); } + for (index, key) in pressed_keys.iter().enumerate() { buttons[index].pressed = *key; } - let keyboard_report = get_keyboard_report( - &mut buttons, - fn_mode, - &mut gui_lock_state, - &mut gui_lock_trigger_index, - ); + let keyboard_report = + get_keyboard_report(&mut buttons, fn_mode, &mut sticky_state, &mut sticky_key); match keyboard.device().write_report(keyboard_report) { Err(UsbHidError::WouldBlock) => {} @@ -248,8 +253,8 @@ fn main() -> ! { /// Update status LED colour based on function layer and capslock /// -/// Normal = green (NORMAL) -/// GUI lock = blue (GUI LOCK) +/// Normal = Off (OFF) +/// STICKY lock = blue/falshing blue (ACTIVITY) /// Capslock active = flashing red (WARNING) /// Error = steady red (ERROR) /// @@ -259,7 +264,8 @@ fn main() -> ! { fn update_status_led( status_led: &mut Ws2812StatusLed, caps_lock_active: &bool, - gui_lock_state: &u8, + sticky_state: &u8, + started: &bool, ) where P: PIOExt + FunctionConfig, I: PinId, @@ -268,10 +274,14 @@ fn update_status_led( { if *caps_lock_active { status_led.update(StatusMode::Warning); - } else if *gui_lock_state != 0 { + } else if *sticky_state == 1 { status_led.update(StatusMode::Activity); - } else { + } else if *sticky_state == 2 { + status_led.update(StatusMode::ActivityFlash); + } else if !(*started) { 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 /// * `fn_mode` - Current function layer -/// * `gui_lock` - Is GUI lock active -/// * `gui_lock_index` - Index of the key pressed after GUI lock was activated +/// * `sticky_state` - Is STICKY lock active +/// * `sticky_key` - the key pressed after STICKY lock was activated fn get_keyboard_report( matrix_keys: &mut [KeyboardButton; NUMBER_OF_KEYS], fn_mode: u8, - gui_lock_state: &mut u8, - gui_lock_trigger_index: &mut u8, + sticky_state: &mut u8, + sticky_key: &mut Keyboard, ) -> [Keyboard; NUMBER_OF_KEYS] { let mut keyboard_report: [Keyboard; NUMBER_OF_KEYS] = [Keyboard::NoEventIndicated; NUMBER_OF_KEYS]; // Filter report based on Fn mode and pressed keys 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 && key.pressed - && index as u8 == layout::GUI_LOCK_BUTTON[0] - && fn_mode == layout::GUI_LOCK_BUTTON[1] - && *gui_lock_state == 0 + && index as u8 == layout::STICKY_BUTTON[0] + && fn_mode == layout::STICKY_BUTTON[1] + && *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 @@ -336,22 +356,11 @@ fn get_keyboard_report( continue; } - /// Index of GUI key in keyboard report - /// Index 36, 37, 38, 45, 46, 47 are not used by any other keys - const GUI_REPORT_INDEX: usize = 47; - - // If GUI lock is active, set LeftGUI key to pressed - // 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; + // If STICKY lock is active, hold index key pressed until STICKY lock key is pressed + // again + if *sticky_state == 1 && key.pressed { + *sticky_key = layout::MAP[key.fn_mode as usize][index]; + *sticky_state = 2; } // 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]; } } + + /// 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 } diff --git a/rp2040/src/status_led.rs b/rp2040/src/status_led.rs index d56af7b..8d95e59 100644 --- a/rp2040/src/status_led.rs +++ b/rp2040/src/status_led.rs @@ -16,7 +16,7 @@ use ws2812_pio::Ws2812Direct; /// * OFF = Syatem offline /// * NORMAL = All system Ok /// * ACTIVITY = System activity -/// * OTHER = Other activity +/// * OTHER = Other activity /// * WARNING = Warning /// * ERROR = Error /// * BOOTLOADER = Bootloader active @@ -26,10 +26,12 @@ pub enum StatusMode { Off = 0, Normal = 1, Activity = 2, - Other = 3, - Warning = 4, - Error = 5, - Bootloader = 6, + ActivityFlash = 3, + Other = 4, + OtherFlash = 5, + Warning = 6, + Error = 7, + Bootloader = 8, } #[warn(dead_code)] @@ -100,22 +102,32 @@ where /// /// Make sure to call this function regularly to keep the LED flashing pub fn update(&mut self, mode: StatusMode) { - let colors: [RGB8; 7] = [ + let colors: [RGB8; 9] = [ (0, 0, 0).into(), // Off (10, 7, 0).into(), // Green (10, 4, 10).into(), // Blue + (10, 4, 10).into(), // Blue + (5, 10, 0).into(), // Orange (5, 10, 0).into(), // Orange (2, 20, 0).into(), // Red (2, 20, 0).into(), // Red (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 .write([colors[mode as usize]].iter().copied()) .unwrap(); 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 .write([colors[0]].iter().copied()) .unwrap();