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
     17static const uint keymat_row_pins[] = { 4, 9, 6, 7 };
     18#else
     19static const uint keymat_row_pins[] = { 4, 5, 6, 7 };
     20#endif
     21
     22static const uint keymat_col_pins[] = { 29, 28, 27, 26, 22, 20 };
     23static_assert(ARRLEN(keymat_row_pins) == KEY_ROWS_HALF);
     24static_assert(ARRLEN(keymat_col_pins) == KEY_COLS);
     25
     26bool keymat_prev[KEY_ROWS][KEY_COLS];
     27bool keymat[KEY_ROWS][KEY_COLS];
     28
     29static uint32_t keymat_modt[KEY_ROWS_HALF][KEY_COLS];
     30
     31void
     32keymat_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
     53bool
     54keymat_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
     86uint32_t
     87keymat_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
    105void
    106keymat_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
    119void
    120keymat_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}