cmdr-keyboard/rp2040/src/hardware.rs

148 lines
4.3 KiB
Rust

//! 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());
}
}