//! Project: CMtec CMDR joystick 25
//! Date:    2023-08-01
//! Author:  Christoffer Martinsson
//! Email:   cm@cmtec.se
//! License: Please refer to LICENSE in root directory

//! Hardware configuration constants and pin definitions for CMDR Joystick 25

// ==================== CRYSTAL AND USB CONSTANTS ====================

pub const XTAL_FREQ_HZ: u32 = 12_000_000u32;
pub const USB_VID: u16 = 0x1209;
pub const USB_PID: u16 = 0x0002;

// ==================== JOYSTICK CONSTANTS ====================

pub const BUTTON_ROWS: usize = 5;
pub const BUTTON_COLS: usize = 5;
pub const NUMBER_OF_BUTTONS: usize = BUTTON_ROWS * BUTTON_COLS;
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;
pub const DEBOUNCE: u8 = 10;
pub const EEPROM_DATA_LENGTH: usize = 25;

// ==================== GPIO PIN DEFINITIONS ====================
pub mod pins {
    /// Extra buttons (TX/RX pins)
    pub const LEFT_EXTRA_BUTTON_PIN: u8 = 1;
    pub const RIGHT_EXTRA_BUTTON_PIN: u8 = 0;

    /// Button matrix row pins
    pub const BUTTON_ROW_PIN_0: u8 = 6;
    pub const BUTTON_ROW_PIN_1: u8 = 8;
    pub const BUTTON_ROW_PIN_2: u8 = 4;
    pub const BUTTON_ROW_PIN_3: u8 = 7;
    pub const BUTTON_ROW_PIN_4: u8 = 5;

    /// Button matrix column pins
    pub const BUTTON_COL_PIN_0: u8 = 9;
    pub const BUTTON_COL_PIN_1: u8 = 10;
    pub const BUTTON_COL_PIN_2: u8 = 11;
    pub const BUTTON_COL_PIN_3: u8 = 12;
    pub const BUTTON_COL_PIN_4: u8 = 13;

    /// ADC pins for gimbal axes
    pub const ADC_LEFT_X_PIN: u8 = 29;
    pub const ADC_LEFT_Y_PIN: u8 = 28;
    pub const ADC_RIGHT_X_PIN: u8 = 27;
    pub const ADC_RIGHT_Y_PIN: u8 = 26;

    /// Status LED pin
    pub const STATUS_LED_PIN: u8 = 16;

    /// I2C pins for EEPROM
    pub const I2C_SDA_PIN: u8 = 14;
    pub const I2C_SCL_PIN: u8 = 15;
}

// ==================== I2C CONFIGURATION ====================

pub mod i2c {
    use fugit::{Rate, RateExtU32};

    pub const I2C_FREQUENCY_HZ: u32 = 400_000;
    pub fn i2c_frequency() -> Rate<u32, 1, 1> {
        I2C_FREQUENCY_HZ.Hz()
    }
    pub const SYSTEM_CLOCK_HZ: u32 = 125_000_000;
    pub fn system_clock() -> Rate<u32, 1, 1> {
        SYSTEM_CLOCK_HZ.Hz()
    }
}

// ==================== TIMER INTERVALS ====================

pub mod timers {
    /// Status LED update interval (250ms)
    pub const STATUS_LED_INTERVAL_MS: u32 = 250;

    /// Scan timer interval (200us)
    pub const SCAN_INTERVAL_US: u32 = 200;

    /// Data processing interval (1200us)
    pub const DATA_PROCESS_INTERVAL_US: u32 = 1200;

    /// USB update interval (10ms)
    pub const USB_UPDATE_INTERVAL_MS: u32 = 10;
}

// ==================== USB DEVICE CONFIGURATION ====================

pub mod usb {
    pub const MANUFACTURER: &str = "CMtec";
    pub const PRODUCT: &str = "CMDR Joystick 25";
    pub const SERIAL_NUMBER: &str = "0001";
}

// ==================== PIN ACCESS MACROS ====================

/// Macro to access GPIO pins using hardware constants
/// This eliminates hardcoded pin numbers in main.rs and ensures constants are used
#[macro_export]
macro_rules! get_pin {
    ($pins:expr, left_extra_button) => {{
        const _: u8 = $crate::hardware::pins::LEFT_EXTRA_BUTTON_PIN;
        $pins.gpio1
    }};
    ($pins:expr, right_extra_button) => {{
        const _: u8 = $crate::hardware::pins::RIGHT_EXTRA_BUTTON_PIN;
        $pins.gpio0
    }};
    ($pins:expr, button_row_0) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_ROW_PIN_0;
        $pins.gpio6
    }};
    ($pins:expr, button_row_1) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_ROW_PIN_1;
        $pins.gpio8
    }};
    ($pins:expr, button_row_2) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_ROW_PIN_2;
        $pins.gpio4
    }};
    ($pins:expr, button_row_3) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_ROW_PIN_3;
        $pins.gpio7
    }};
    ($pins:expr, button_row_4) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_ROW_PIN_4;
        $pins.gpio5
    }};
    ($pins:expr, button_col_0) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_COL_PIN_0;
        $pins.gpio9
    }};
    ($pins:expr, button_col_1) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_COL_PIN_1;
        $pins.gpio10
    }};
    ($pins:expr, button_col_2) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_COL_PIN_2;
        $pins.gpio11
    }};
    ($pins:expr, button_col_3) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_COL_PIN_3;
        $pins.gpio12
    }};
    ($pins:expr, button_col_4) => {{
        const _: u8 = $crate::hardware::pins::BUTTON_COL_PIN_4;
        $pins.gpio13
    }};
    ($pins:expr, adc_left_x) => {{
        const _: u8 = $crate::hardware::pins::ADC_LEFT_X_PIN;
        $pins.gpio29
    }};
    ($pins:expr, adc_left_y) => {{
        const _: u8 = $crate::hardware::pins::ADC_LEFT_Y_PIN;
        $pins.gpio28
    }};
    ($pins:expr, adc_right_x) => {{
        const _: u8 = $crate::hardware::pins::ADC_RIGHT_X_PIN;
        $pins.gpio27
    }};
    ($pins:expr, adc_right_y) => {{
        const _: u8 = $crate::hardware::pins::ADC_RIGHT_Y_PIN;
        $pins.gpio26
    }};
    ($pins:expr, status_led) => {{
        const _: u8 = $crate::hardware::pins::STATUS_LED_PIN;
        $pins.gpio16
    }};
    ($pins:expr, i2c_sda) => {{
        const _: u8 = $crate::hardware::pins::I2C_SDA_PIN;
        $pins.gpio14
    }};
    ($pins:expr, i2c_scl) => {{
        const _: u8 = $crate::hardware::pins::I2C_SCL_PIN;
        $pins.gpio15
    }};
}
