//! Hardware configuration and timing constants for the CMDR Keyboard 42. /// External crystal frequency (Hz). pub const XTAL_FREQ_HZ: u32 = 12_000_000; /// Debounce scans required before a key state toggles. pub const MATRIX_DEBOUNCE_SCANS_PRESS: u8 = 2; pub const MATRIX_DEBOUNCE_SCANS_RELEASE: u8 = 3; /// Initial scan iterations before trusting key state. pub const INITIAL_SCAN_PASSES: usize = 50; /// Button matrix geometry. pub const KEY_ROWS: usize = 4; pub const KEY_COLS: usize = 12; pub const NUMBER_OF_KEYS: usize = KEY_ROWS * KEY_COLS; /// USB identification constants. pub mod usb { pub const VID: u16 = 0x1209; pub const PID: u16 = 0x0001; pub const MANUFACTURER: &str = "CMtec"; pub const PRODUCT: &str = "CMDR Keyboard 42"; pub const SERIAL_NUMBER: &str = "0001"; } /// Timing cadence helpers used throughout the firmware. pub mod timers { pub const USB_REPORT_INTERVAL_MS: u32 = 10; pub const USB_TICK_INTERVAL_US: u32 = 250; pub const STATUS_LED_INTERVAL_MS: u32 = 4; pub const IDLE_TIMEOUT_MS: u32 = 5_000; } /// Physical GPIO assignments for the RP2040. pub mod pins { pub const BUTTON_ROW_0: u8 = 0; pub const BUTTON_ROW_1: u8 = 1; pub const BUTTON_ROW_2: u8 = 29; pub const BUTTON_ROW_3: u8 = 28; pub const BUTTON_COL_0: u8 = 12; pub const BUTTON_COL_1: u8 = 13; pub const BUTTON_COL_2: u8 = 14; pub const BUTTON_COL_3: u8 = 15; pub const BUTTON_COL_4: u8 = 26; pub const BUTTON_COL_5: u8 = 27; pub const BUTTON_COL_6: u8 = 7; pub const BUTTON_COL_7: u8 = 8; pub const BUTTON_COL_8: u8 = 6; pub const BUTTON_COL_9: u8 = 9; pub const BUTTON_COL_10: u8 = 10; pub const BUTTON_COL_11: u8 = 11; pub const STATUS_LED: u8 = 16; } /// Convenience macro mirroring the joystick repository for fetching typed pins. #[macro_export] macro_rules! get_pin { ($pins:expr, button_row_0) => {{ const _: u8 = $crate::hardware::pins::BUTTON_ROW_0; $pins.gpio0 }}; ($pins:expr, button_row_1) => {{ const _: u8 = $crate::hardware::pins::BUTTON_ROW_1; $pins.gpio1 }}; ($pins:expr, button_row_2) => {{ const _: u8 = $crate::hardware::pins::BUTTON_ROW_2; $pins.gpio29 }}; ($pins:expr, button_row_3) => {{ const _: u8 = $crate::hardware::pins::BUTTON_ROW_3; $pins.gpio28 }}; ($pins:expr, button_col_0) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_0; $pins.gpio12 }}; ($pins:expr, button_col_1) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_1; $pins.gpio13 }}; ($pins:expr, button_col_2) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_2; $pins.gpio14 }}; ($pins:expr, button_col_3) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_3; $pins.gpio15 }}; ($pins:expr, button_col_4) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_4; $pins.gpio26 }}; ($pins:expr, button_col_5) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_5; $pins.gpio27 }}; ($pins:expr, button_col_6) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_6; $pins.gpio7 }}; ($pins:expr, button_col_7) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_7; $pins.gpio8 }}; ($pins:expr, button_col_8) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_8; $pins.gpio6 }}; ($pins:expr, button_col_9) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_9; $pins.gpio9 }}; ($pins:expr, button_col_10) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_10; $pins.gpio10 }}; ($pins:expr, button_col_11) => {{ const _: u8 = $crate::hardware::pins::BUTTON_COL_11; $pins.gpio11 }}; ($pins:expr, status_led) => {{ const _: u8 = $crate::hardware::pins::STATUS_LED; $pins.gpio16 }}; } #[cfg(all(test, feature = "std"))] mod tests { use super::*; #[test] fn number_of_keys_matches_rows_and_cols() { assert_eq!(NUMBER_OF_KEYS, KEY_ROWS * KEY_COLS); } #[test] fn usb_metadata_is_consistent() { assert_ne!(usb::VID, 0); assert_ne!(usb::PID, 0); assert!(!usb::MANUFACTURER.is_empty()); assert!(!usb::PRODUCT.is_empty()); } }