sxkbd

Firmware for RP2040-based corne split keyboard
git clone https://git.sinitax.com/sinitax/sxkbd
Log | Files | Refs | Submodules | README | LICENSE | sfeed.txt

keymat.c (2940B)


      1 #include "keymat.h"
      2 
      3 #include "keymap.h"
      4 #include "split.h"
      5 #include "util.h"
      6 
      7 #include "bsp/board.h"
      8 #include "pico/types.h"
      9 #include "hardware/gpio.h"
     10 #include "hardware/timer.h"
     11 
     12 #include <string.h>
     13 
     14 #define DEBOUNCE_MS 50
     15 
     16 #ifdef BAD_GPIO_MITIGATION
     17 static const uint keymat_row_pins[] = { 4, 9, 6, 7 };
     18 #else
     19 static const uint keymat_row_pins[] = { 4, 5, 6, 7 };
     20 #endif
     21 
     22 static const uint keymat_col_pins[] = { 29, 28, 27, 26, 22, 20 };
     23 static_assert(ARRLEN(keymat_row_pins) == KEY_ROWS_HALF);
     24 static_assert(ARRLEN(keymat_col_pins) == KEY_COLS);
     25 
     26 bool keymat_prev[KEY_ROWS][KEY_COLS];
     27 bool keymat[KEY_ROWS][KEY_COLS];
     28 
     29 static uint32_t keymat_modt[KEY_ROWS_HALF][KEY_COLS];
     30 
     31 void
     32 keymat_init(void)
     33 {
     34 	uint x, y;
     35 
     36 	for (x = 0; x < KEY_COLS; x++) {
     37 		gpio_init(keymat_col_pins[x]);
     38 		gpio_set_dir(keymat_col_pins[x], GPIO_IN);
     39 		gpio_set_drive_strength(keymat_col_pins[x], GPIO_DRIVE_STRENGTH_2MA);
     40 		gpio_set_slew_rate(keymat_col_pins[x], GPIO_SLEW_RATE_FAST);
     41 		gpio_pull_up(keymat_col_pins[x]);
     42 	}
     43 
     44 	for (y = 0; y < KEY_ROWS_HALF; y++) {
     45 		gpio_init(keymat_row_pins[y]);
     46 		gpio_set_dir(keymat_row_pins[y], GPIO_OUT);
     47 		gpio_set_drive_strength(keymat_col_pins[x], GPIO_DRIVE_STRENGTH_2MA);
     48 		gpio_set_slew_rate(keymat_row_pins[y], GPIO_SLEW_RATE_FAST);
     49 		gpio_put(keymat_row_pins[y], 0);
     50 	}
     51 }
     52 
     53 bool
     54 keymat_scan(void)
     55 {
     56 	bool (*keymat_half)[KEY_COLS];
     57 	bool state, modified;
     58 	uint32_t now_ms;
     59 	uint x, y;
     60 
     61 	now_ms = board_millis();
     62 	modified = false;
     63 
     64 	memcpy(keymat_prev, keymat, sizeof(keymat));
     65 	keymat_half = KEYMAT_HALF(keymat, SPLIT_SIDE);
     66 	for (y = 0; y < KEY_ROWS_HALF; y++) {
     67 		gpio_put(keymat_row_pins[y], 0);
     68 		busy_wait_us(5);
     69 		for (x = 0; x < KEY_COLS; x++) {
     70 			if (keymat_modt[y][x] > now_ms - DEBOUNCE_MS)
     71 				continue;
     72 			state = !gpio_get(keymat_col_pins[x]);
     73 			if (state != keymat_half[y][x]) {
     74 				modified = true;
     75 				keymat_half[y][x] = state;
     76 				keymat_modt[y][x] = now_ms;
     77 			}
     78 		}
     79 		gpio_put(keymat_row_pins[y], 1);
     80 		busy_wait_us(5);
     81 	}
     82 
     83 	return modified;
     84 }
     85 
     86 uint32_t
     87 keymat_encode_half(int side)
     88 {
     89 	bool (*keymat_half)[KEY_COLS];
     90 	uint32_t mask;
     91 	uint x, y;
     92 
     93 	mask = 0;
     94 	keymat_half = KEYMAT_HALF(keymat, side);
     95 	for (y = 0; y < KEY_ROWS_HALF; y++) {
     96 		for (x = 0; x < KEY_COLS; x++) {
     97 			if (keymat_half[y][x])
     98 				mask |= 1 << (y * KEY_COLS + x);
     99 		}
    100 	}
    101 
    102 	return mask;
    103 }
    104 
    105 void
    106 keymat_decode_half(int side, uint32_t mask)
    107 {
    108 	bool (*keymat_half)[KEY_COLS];
    109 	uint x, y;
    110 
    111 	keymat_half = KEYMAT_HALF(keymat, side);
    112 	for (y = 0; y < KEY_ROWS_HALF; y++) {
    113 		for (x = 0; x < KEY_COLS; x++) {
    114 			keymat_half[y][x] = (mask >> (y * KEY_COLS + x)) & 1;
    115 		}
    116 	}
    117 }
    118 
    119 void
    120 keymat_debug(void)
    121 {
    122 	uint x, y;
    123 
    124 	if (log_level_min > LOG_DEBUG)
    125 		return;
    126 
    127 	for (y = 0; y < KEY_ROWS; y++) {
    128 		for (x = 0; x < KEY_COLS; x++) {
    129 			if (!keymat_prev[y][x] && keymat[y][x])
    130 				DEBUG(LOG_KEYMAT, "Key pressed: %u %u", x, y);
    131 			else if (keymat_prev[y][x] && !keymat[y][x])
    132 				DEBUG(LOG_KEYMAT, "Key released: %u %u", x, y);
    133 		}
    134 	}
    135 }