diff --git a/src/board/system76/addw1/gpio.c b/src/board/system76/addw1/gpio.c index 12c07665a..db886140d 100644 --- a/src/board/system76/addw1/gpio.c +++ b/src/board/system76/addw1/gpio.c @@ -105,11 +105,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_OUT; // KB-SO16 - GPCRC3 = GPIO_IN | GPIO_UP; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET#_EC GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN | GPIO_UP; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/addw2/gpio.c b/src/board/system76/addw2/gpio.c index 57d2e5fac..5755eb59b 100644 --- a/src/board/system76/addw2/gpio.c +++ b/src/board/system76/addw2/gpio.c @@ -114,11 +114,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET#_EC GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/addw3/gpio.c b/src/board/system76/addw3/gpio.c index 61b124c8c..c01706ba8 100644 --- a/src/board/system76/addw3/gpio.c +++ b/src/board/system76/addw3/gpio.c @@ -128,11 +128,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB_SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB_SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/bonw14/gpio.c b/src/board/system76/bonw14/gpio.c index 8665eb8d5..f41328136 100644 --- a/src/board/system76/bonw14/gpio.c +++ b/src/board/system76/bonw14/gpio.c @@ -106,11 +106,11 @@ void gpio_init() { // KBC_SMBus_DAT1 GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/bonw15/gpio.c b/src/board/system76/bonw15/gpio.c index 86eb953b6..7a25af150 100644 --- a/src/board/system76/bonw15/gpio.c +++ b/src/board/system76/bonw15/gpio.c @@ -131,11 +131,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PLVDD_RST_EC GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/common/kbscan.c b/src/board/system76/common/kbscan.c index 2b57248e7..aac15fa51 100644 --- a/src/board/system76/common/kbscan.c +++ b/src/board/system76/common/kbscan.c @@ -19,6 +19,12 @@ #define KM_NKEY 0 #endif // KM_NKEY +// Debounce time in milliseconds +#define DEBOUNCE_DELAY 5 + +// Deselect all columns for reading +#define KBSCAN_MATRIX_NONE 0xFF + bool kbscan_fn_held = false; bool kbscan_esc_held = false; @@ -38,90 +44,58 @@ static inline bool matrix_position_is_fn(uint8_t row, uint8_t col) { return (row == MATRIX_FN_OUTPUT) && (col == MATRIX_FN_INPUT); } +// Initialize the Keyboard Matrix Scan Controller in KBS (Normal) mode for +// reading keyboard input. void kbscan_init(void) { - KSOCTRL = 0x05; - KSICTRLR = 0x04; - - // Set all outputs to GPIO mode, low, and inputs + // KSO[15:0]: Enable pull-up, set to KBS mode, open-drain + // NOTE: KSO[17:16] ALT mode and pull-up configured by GPCRC + KSOCTRL = BIT(2) | BIT(0); + KSOHGCTRL = 0; + KSOLGCTRL = 0; + // XXX: Still set outputs low? KSOL = 0; - KSOLGCTRL = 0xFF; - KSOLGOEN = 0; KSOH1 = 0; - KSOHGCTRL = 0xFF; - KSOHGOEN = 0; KSOH2 = 0; - // Set all inputs to KBS mode, low, and inputs + // KSI[7:0]: Enable pull-up, set to KBS mode + KSICTRLR = BIT(2); KSIGCTRL = 0; - KSIGOEN = 0; - KSIGDAT = 0; } -// Debounce time in milliseconds -#define DEBOUNCE_DELAY 5 - -static uint8_t kbscan_get_row(uint8_t i) { +// Read the state of the row for the selected column. +static inline uint8_t kbscan_get_row(void) { // Report all keys as released when lid is closed if (!lid_state) { return 0; } - // Set current line as output - if (i < 8) { - KSOLGOEN = BIT(i); - KSOHGOEN = 0; -#if KM_OUT >= 17 - GPCRC3 = GPIO_IN; -#endif -#if KM_OUT >= 18 - GPCRC5 = GPIO_IN; -#endif - } else if (i < 16) { - KSOLGOEN = 0; - KSOHGOEN = BIT((i - 8)); -#if KM_OUT >= 17 - GPCRC3 = GPIO_IN; -#endif -#if KM_OUT >= 18 - GPCRC5 = GPIO_IN; -#endif - } else if (i == 16) { - KSOLGOEN = 0; - KSOHGOEN = 0; -#if KM_OUT >= 17 - GPCRC3 = GPIO_OUT; -#endif -#if KM_OUT >= 18 - GPCRC5 = GPIO_IN; -#endif - } else if (i == 17) { - KSOLGOEN = 0; - KSOHGOEN = 0; -#if KM_OUT >= 17 - GPCRC3 = GPIO_IN; -#endif -#if KM_OUT >= 18 - GPCRC5 = GPIO_OUT; -#endif + // Invert KSI for positive logic of pressed keys. + return ~KSI; +} + +// Assert the specified column for reading the row. +static void kbscan_set_column(uint8_t col) { + if (col == KBSCAN_MATRIX_NONE) { + // Disable reading from all columns + KSOL = 0xFF; + KSOH1 = 0xFF; + KSOH2 = 0x3; + } else { + // Assert the specific bit corresponding to the column + uint32_t colbit = ~BIT(col); + KSOL = colbit & 0xFF; + KSOH1 = (colbit >> 8) & 0xFF; + KSOH2 = (colbit >> 16) & 0x03; } -#if KM_OUT >= 17 - GPDRC &= ~BIT(3); -#endif -#if KM_OUT >= 18 - GPDRC &= ~BIT(5); -#endif - - // TODO: figure out optimal delay - delay_ticks(20); - return ~KSI; + // Wait for matrix to stabilize + delay_ticks(20); } #if KM_NKEY -static bool kbscan_has_ghost_in_row(uint8_t row, uint8_t rowdata) { - // Use arguments - row = row; - rowdata = rowdata; +static bool kbscan_row_has_ghost(uint8_t *matrix, uint8_t col) { + (void)matrix; + (void)col; return false; } #else // KM_NKEY @@ -129,32 +103,22 @@ static inline bool popcount_more_than_one(uint8_t rowdata) { return rowdata & (rowdata - 1); } -static uint8_t kbscan_get_real_keys(uint8_t row, uint8_t rowdata) { - // Remove any "active" blanks from the matrix. - uint8_t realdata = 0; - for (uint8_t col = 0; col < KM_IN; col++) { - // This tests the default keymap intentionally, to avoid blanks in the - // dynamic keymap - if (KEYMAP[0][row][col] && (rowdata & BIT(col))) { - realdata |= BIT(col); - } - } - - return realdata; -} - -static bool kbscan_has_ghost_in_row(uint8_t row, uint8_t rowdata) { - rowdata = kbscan_get_real_keys(row, rowdata); +static bool kbscan_row_has_ghost(uint8_t *matrix, uint8_t col) { + uint8_t rowdata = matrix[col]; - // No ghosts exist when less than 2 keys in the row are active. + // No ghosts exist when less than 2 keys in the row are active. if (!popcount_more_than_one(rowdata)) { return false; } // Check against other rows to see if more than one column matches. for (uint8_t i = 0; i < KM_OUT; i++) { - uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i)); - if (i != row && popcount_more_than_one(otherrow & rowdata)) { + if (i == col) { + continue; + } + + uint8_t common = rowdata & matrix[i]; + if (popcount_more_than_one(common)) { return true; } } @@ -316,6 +280,7 @@ void kbscan_event(void) { uint8_t layer = kbscan_layer; static uint8_t kbscan_last_layer[KM_OUT][KM_IN] = { { 0 } }; static bool kbscan_ghost[KM_OUT] = { false }; + uint8_t matrix_curr[KM_OUT]; static bool debounce = false; static uint32_t debounce_time = 0; @@ -336,11 +301,19 @@ void kbscan_event(void) { } } + // Read the current state of the hardware matrix + for (uint8_t i = 0; i < KM_OUT; i++) { + kbscan_set_column(i); + matrix_curr[i] = kbscan_get_row(); + } + // Disable reading any keys + kbscan_set_column(KBSCAN_MATRIX_NONE); + for (uint8_t i = 0; i < KM_OUT; i++) { - uint8_t new = kbscan_get_row(i); + uint8_t new = matrix_curr[i]; uint8_t last = kbscan_matrix[i]; if (new != last) { - if (kbscan_has_ghost_in_row(i, new)) { + if (kbscan_row_has_ghost(matrix_curr, i)) { continue; } @@ -432,17 +405,4 @@ void kbscan_event(void) { } kbscan_layer = layer; - - // Reset all lines to inputs - KSOLGOEN = 0; - KSOHGOEN = 0; -#if KM_OUT >= 17 - GPCRC3 = GPIO_IN; -#endif -#if KM_OUT >= 18 - GPCRC5 = GPIO_IN; -#endif - - // TODO: figure out optimal delay - delay_ticks(10); } diff --git a/src/board/system76/darp5/gpio.c b/src/board/system76/darp5/gpio.c index 1c98a32a3..b4f55fd41 100644 --- a/src/board/system76/darp5/gpio.c +++ b/src/board/system76/darp5/gpio.c @@ -105,11 +105,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KSO16 (Darter) - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_OUT; // KSO17 (Darter) - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/darp7/gpio.c b/src/board/system76/darp7/gpio.c index 50d01d760..ee4538fd0 100644 --- a/src/board/system76/darp7/gpio.c +++ b/src/board/system76/darp7/gpio.c @@ -118,11 +118,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/darp8/gpio.c b/src/board/system76/darp8/gpio.c index 7571ded6d..f8d81b134 100644 --- a/src/board/system76/darp8/gpio.c +++ b/src/board/system76/darp8/gpio.c @@ -120,11 +120,11 @@ void gpio_init(void) { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // Not connected GPCRC6 = GPIO_IN | GPIO_DOWN; // LED_ACIN diff --git a/src/board/system76/galp3-c/gpio.c b/src/board/system76/galp3-c/gpio.c index 52ce2da2c..4e4703fe8 100644 --- a/src/board/system76/galp3-c/gpio.c +++ b/src/board/system76/galp3-c/gpio.c @@ -104,11 +104,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_IN | GPIO_UP; // KSO16 (Darter) - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_OUT; // KSO17 (Darter) - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/gaze15/gpio.c b/src/board/system76/gaze15/gpio.c index 8ae48bf54..f6f192d94 100644 --- a/src/board/system76/gaze15/gpio.c +++ b/src/board/system76/gaze15/gpio.c @@ -109,11 +109,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET#_EC GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/gaze16-3050/gpio.c b/src/board/system76/gaze16-3050/gpio.c index d80b00438..3c0d080e5 100644 --- a/src/board/system76/gaze16-3050/gpio.c +++ b/src/board/system76/gaze16-3050/gpio.c @@ -114,11 +114,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // EC_SYS_PWROK GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/gaze16-3060/gpio.c b/src/board/system76/gaze16-3060/gpio.c index a5e0d229c..1cfa9cdc7 100644 --- a/src/board/system76/gaze16-3060/gpio.c +++ b/src/board/system76/gaze16-3060/gpio.c @@ -114,11 +114,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // EC_SYS_PWROK GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/gaze17-3050/gpio.c b/src/board/system76/gaze17-3050/gpio.c index 203d79ee7..aa0beb777 100644 --- a/src/board/system76/gaze17-3050/gpio.c +++ b/src/board/system76/gaze17-3050/gpio.c @@ -112,11 +112,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB_SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB_SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // CPU_C10_GATE# GPCRC6 = GPIO_IN; // BKL_EN diff --git a/src/board/system76/gaze17-3060/gpio.c b/src/board/system76/gaze17-3060/gpio.c index 74dfcf684..60fb1099a 100644 --- a/src/board/system76/gaze17-3060/gpio.c +++ b/src/board/system76/gaze17-3060/gpio.c @@ -118,11 +118,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB_SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB_SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PCH_PWROK_EC GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/oryp11/gpio.c b/src/board/system76/oryp11/gpio.c index 89bfad2db..432a39dad 100644 --- a/src/board/system76/oryp11/gpio.c +++ b/src/board/system76/oryp11/gpio.c @@ -131,11 +131,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB_SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB_SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // SYS_PWROK_EC GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/oryp5/gpio.c b/src/board/system76/oryp5/gpio.c index 38cd24669..31bb7eb73 100644 --- a/src/board/system76/oryp5/gpio.c +++ b/src/board/system76/oryp5/gpio.c @@ -102,11 +102,11 @@ void gpio_init(void) { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_WIGIG_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/oryp6/gpio.c b/src/board/system76/oryp6/gpio.c index 37ef52431..6e583ddeb 100644 --- a/src/board/system76/oryp6/gpio.c +++ b/src/board/system76/oryp6/gpio.c @@ -112,11 +112,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/oryp7/gpio.c b/src/board/system76/oryp7/gpio.c index ac5462a47..75efc0d74 100644 --- a/src/board/system76/oryp7/gpio.c +++ b/src/board/system76/oryp7/gpio.c @@ -111,11 +111,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PM_PWROK GPCRC6 = GPIO_OUT; // LED_ACIN diff --git a/src/board/system76/oryp8/gpio.c b/src/board/system76/oryp8/gpio.c index 0e55d2869..81e7f7b23 100644 --- a/src/board/system76/oryp8/gpio.c +++ b/src/board/system76/oryp8/gpio.c @@ -114,11 +114,11 @@ void gpio_init() { // SMD_VGA_THERM GPCRC2 = GPIO_ALT; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PCH_PWROK_EC GPCRC6 = GPIO_OUT; // BKL_EN diff --git a/src/board/system76/oryp9/gpio.c b/src/board/system76/oryp9/gpio.c index 94c8cf8d3..6e0678a3f 100644 --- a/src/board/system76/oryp9/gpio.c +++ b/src/board/system76/oryp9/gpio.c @@ -123,11 +123,11 @@ void gpio_init(void) { // SMD_VGA_THERM GPCRC2 = GPIO_ALT | GPIO_UP; // KB-SO16 - GPCRC3 = GPIO_IN; + GPCRC3 = GPIO_ALT | GPIO_UP; // CNVI_DET# GPCRC4 = GPIO_IN | GPIO_UP; // KB-SO17 - GPCRC5 = GPIO_IN; + GPCRC5 = GPIO_ALT | GPIO_UP; // PCH_PWROK_EC GPCRC6 = GPIO_OUT; // BKL_EN