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}