196 lines
6.3 KiB
Rust
196 lines
6.3 KiB
Rust
//! Hardware configuration for CMDR Joystick (RP2040)
|
|
//!
|
|
//! Mirrors the structure introduced for the CMDR Keyboard firmware so that
|
|
//! bring-up, pin management, and timing constants follow the same layout.
|
|
|
|
use rp2040_hal::gpio::Pins;
|
|
use rp2040_hal::gpio::{
|
|
self, DynPinId, FunctionI2C, FunctionPio0, FunctionSioInput, FunctionSioOutput, Pin, PullNone,
|
|
PullUp,
|
|
};
|
|
|
|
/// External crystal frequency (Hz).
|
|
pub const XTAL_FREQ_HZ: u32 = 12_000_000;
|
|
|
|
/// USB Vendor ID/Product ID.
|
|
pub const USB_VID: u16 = 0x1209;
|
|
pub const USB_PID: u16 = 0x0002;
|
|
|
|
/// Button matrix geometry (rows/cols) and count.
|
|
pub const BUTTON_ROWS: usize = 5;
|
|
pub const BUTTON_COLS: usize = 5;
|
|
pub const NUMBER_OF_BUTTONS: usize = BUTTON_ROWS * BUTTON_COLS;
|
|
|
|
/// ADC characteristics.
|
|
pub const ADC_MIN: u16 = 0;
|
|
pub const ADC_MAX: u16 = 4095;
|
|
pub const AXIS_CENTER: u16 = (ADC_MIN + ADC_MAX) / 2;
|
|
pub const NBR_OF_GIMBAL_AXIS: usize = 4;
|
|
|
|
/// Debounce thresholds.
|
|
pub const MATRIX_DEBOUNCE_SCANS: u8 = 15;
|
|
pub const MIN_PRESS_SPACING_SCANS: u32 = 25; // ~5ms @ 200µs cadence
|
|
|
|
/// EEPROM storage length (calibration data + gimbal mode).
|
|
pub const EEPROM_DATA_LENGTH: usize = 25;
|
|
|
|
/// USB string descriptors.
|
|
pub mod usb {
|
|
pub const MANUFACTURER: &str = "CMtec";
|
|
pub const PRODUCT: &str = "CMDR Joystick";
|
|
pub const SERIAL_NUMBER: &str = "0001";
|
|
}
|
|
|
|
/// Timing cadences.
|
|
pub mod timers {
|
|
pub const STATUS_LED_INTERVAL_MS: u32 = 40;
|
|
pub const SCAN_INTERVAL_US: u32 = 200;
|
|
pub const USB_UPDATE_INTERVAL_MS: u32 = 1;
|
|
pub const USB_ACTIVITY_TIMEOUT_MS: u32 = 5_000;
|
|
}
|
|
|
|
/// I2C helpers.
|
|
pub mod i2c {
|
|
use eeprom24x::SlaveAddr;
|
|
use fugit::{Rate, RateExtU32};
|
|
|
|
pub const FREQUENCY_HZ: u32 = 400_000;
|
|
pub const SYSTEM_CLOCK_HZ: u32 = 125_000_000;
|
|
|
|
pub fn frequency() -> Rate<u32, 1, 1> {
|
|
FREQUENCY_HZ.Hz()
|
|
}
|
|
|
|
pub fn system_clock() -> Rate<u32, 1, 1> {
|
|
SYSTEM_CLOCK_HZ.Hz()
|
|
}
|
|
|
|
pub const EEPROM_ADDRESS: SlaveAddr = SlaveAddr::Alternative(false, false, false);
|
|
}
|
|
|
|
/// Raw GPIO constants retained for documentation/reference.
|
|
pub mod pins {
|
|
pub const LEFT_EXTRA_BUTTON: u8 = 1;
|
|
pub const RIGHT_EXTRA_BUTTON: u8 = 0;
|
|
pub const BUTTON_ROW_0: u8 = 6;
|
|
pub const BUTTON_ROW_1: u8 = 8;
|
|
pub const BUTTON_ROW_2: u8 = 4;
|
|
pub const BUTTON_ROW_3: u8 = 7;
|
|
pub const BUTTON_ROW_4: u8 = 5;
|
|
pub const BUTTON_COL_0: u8 = 9;
|
|
pub const BUTTON_COL_1: u8 = 10;
|
|
pub const BUTTON_COL_2: u8 = 11;
|
|
pub const BUTTON_COL_3: u8 = 12;
|
|
pub const BUTTON_COL_4: u8 = 13;
|
|
pub const ADC_LEFT_X: u8 = 29;
|
|
pub const ADC_LEFT_Y: u8 = 28;
|
|
pub const ADC_RIGHT_X: u8 = 27;
|
|
pub const ADC_RIGHT_Y: u8 = 26;
|
|
pub const STATUS_LED: u8 = 16;
|
|
pub const I2C_SDA: u8 = 14;
|
|
pub const I2C_SCL: u8 = 15;
|
|
}
|
|
|
|
/// Matrix row pins (dynamic to simplify scanning code).
|
|
pub type MatrixRowPin = Pin<DynPinId, FunctionSioInput, PullUp>;
|
|
/// Matrix column pins (dynamic push-pull outputs).
|
|
pub type MatrixColPin = Pin<DynPinId, FunctionSioOutput, PullNone>;
|
|
/// Extra buttons (pull-up inputs).
|
|
pub type ExtraButtonPin = Pin<DynPinId, FunctionSioInput, PullUp>;
|
|
/// Status LED pin configured for PIO output.
|
|
pub type StatusLedPin = Pin<gpio::bank0::Gpio16, FunctionPio0, PullNone>;
|
|
/// I2C SDA/SCL pins after reconfiguration.
|
|
pub type I2cSdaPin = Pin<gpio::bank0::Gpio14, FunctionI2C, PullUp>;
|
|
pub type I2cSclPin = Pin<gpio::bank0::Gpio15, FunctionI2C, PullUp>;
|
|
|
|
/// Analog axis input pins (remain as SIO inputs until wrapped by `AdcPin`).
|
|
pub struct AxisInputs {
|
|
pub left_x: Pin<gpio::bank0::Gpio29, FunctionSioInput, PullNone>,
|
|
pub left_y: Pin<gpio::bank0::Gpio28, FunctionSioInput, PullNone>,
|
|
pub right_x: Pin<gpio::bank0::Gpio27, FunctionSioInput, PullNone>,
|
|
pub right_y: Pin<gpio::bank0::Gpio26, FunctionSioInput, PullNone>,
|
|
}
|
|
|
|
/// Bundle returned by `split_board_pins`.
|
|
pub struct BoardPins {
|
|
pub matrix_rows: [MatrixRowPin; BUTTON_ROWS],
|
|
pub matrix_cols: [MatrixColPin; BUTTON_COLS],
|
|
pub left_extra_button: ExtraButtonPin,
|
|
pub right_extra_button: ExtraButtonPin,
|
|
pub axis_inputs: AxisInputs,
|
|
pub status_led: StatusLedPin,
|
|
pub i2c_sda: I2cSdaPin,
|
|
pub i2c_scl: I2cSclPin,
|
|
}
|
|
|
|
impl BoardPins {
|
|
pub fn new(pins: Pins) -> Self {
|
|
let row0 = pins.gpio6.into_pull_up_input().into_dyn_pin();
|
|
let row1 = pins.gpio8.into_pull_up_input().into_dyn_pin();
|
|
let row2 = pins.gpio4.into_pull_up_input().into_dyn_pin();
|
|
let row3 = pins.gpio7.into_pull_up_input().into_dyn_pin();
|
|
let row4 = pins.gpio5.into_pull_up_input().into_dyn_pin();
|
|
|
|
let col0 = pins
|
|
.gpio9
|
|
.into_push_pull_output()
|
|
.into_pull_type::<PullNone>()
|
|
.into_dyn_pin();
|
|
let col1 = pins
|
|
.gpio10
|
|
.into_push_pull_output()
|
|
.into_pull_type::<PullNone>()
|
|
.into_dyn_pin();
|
|
let col2 = pins
|
|
.gpio11
|
|
.into_push_pull_output()
|
|
.into_pull_type::<PullNone>()
|
|
.into_dyn_pin();
|
|
let col3 = pins
|
|
.gpio12
|
|
.into_push_pull_output()
|
|
.into_pull_type::<PullNone>()
|
|
.into_dyn_pin();
|
|
let col4 = pins
|
|
.gpio13
|
|
.into_push_pull_output()
|
|
.into_pull_type::<PullNone>()
|
|
.into_dyn_pin();
|
|
|
|
let left_extra = pins.gpio1.into_pull_up_input().into_dyn_pin();
|
|
let right_extra = pins.gpio0.into_pull_up_input().into_dyn_pin();
|
|
|
|
let axis_inputs = AxisInputs {
|
|
left_x: pins.gpio29.into_floating_input(),
|
|
left_y: pins.gpio28.into_floating_input(),
|
|
right_x: pins.gpio27.into_floating_input(),
|
|
right_y: pins.gpio26.into_floating_input(),
|
|
};
|
|
|
|
let status_led = pins
|
|
.gpio16
|
|
.into_function::<FunctionPio0>()
|
|
.into_pull_type::<PullNone>();
|
|
|
|
let i2c_sda = pins
|
|
.gpio14
|
|
.into_function::<FunctionI2C>()
|
|
.into_pull_type::<PullUp>();
|
|
let i2c_scl = pins
|
|
.gpio15
|
|
.into_function::<FunctionI2C>()
|
|
.into_pull_type::<PullUp>();
|
|
|
|
Self {
|
|
matrix_rows: [row0, row1, row2, row3, row4],
|
|
matrix_cols: [col0, col1, col2, col3, col4],
|
|
left_extra_button: left_extra,
|
|
right_extra_button: right_extra,
|
|
axis_inputs,
|
|
status_led,
|
|
i2c_sda,
|
|
i2c_scl,
|
|
}
|
|
}
|
|
}
|