keyboard stuff
1#include "matrix.h"
2#include "debounce.h"
3#include "wait.h"
4#include "print.h"
5#include "debug.h"
6
7#ifdef SPLIT_KEYBOARD
8# include "split_common/split_util.h"
9# include "split_common/transactions.h"
10# include <string.h>
11#endif
12
13#ifndef MATRIX_IO_DELAY
14# define MATRIX_IO_DELAY 30
15#endif
16
17/* matrix state(1:on, 0:off) */
18matrix_row_t raw_matrix[MATRIX_ROWS];
19matrix_row_t matrix[MATRIX_ROWS];
20
21#ifdef SPLIT_KEYBOARD
22// row offsets for each hand
23uint8_t thisHand, thatHand;
24#endif
25
26#ifdef MATRIX_MASKED
27extern const matrix_row_t matrix_mask[];
28#endif
29
30// user-defined overridable functions
31
32__attribute__((weak)) void matrix_init_kb(void) {
33 matrix_init_user();
34}
35
36__attribute__((weak)) void matrix_scan_kb(void) {
37 matrix_scan_user();
38}
39
40__attribute__((weak)) void matrix_init_user(void) {}
41
42__attribute__((weak)) void matrix_scan_user(void) {}
43
44// helper functions
45
46inline uint8_t matrix_rows(void) {
47 return MATRIX_ROWS;
48}
49
50inline uint8_t matrix_cols(void) {
51 return MATRIX_COLS;
52}
53
54inline bool matrix_is_on(uint8_t row, uint8_t col) {
55 return (matrix[row] & ((matrix_row_t)1 << col));
56}
57
58inline matrix_row_t matrix_get_row(uint8_t row) {
59 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
60 // switch blocker installed and the switch is always pressed.
61#ifdef MATRIX_MASKED
62 return matrix[row] & matrix_mask[row];
63#else
64 return matrix[row];
65#endif
66}
67
68#if (MATRIX_COLS <= 8)
69# define print_matrix_header() print("\nr/c 01234567\n")
70# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
71#elif (MATRIX_COLS <= 16)
72# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
73# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
74#elif (MATRIX_COLS <= 32)
75# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
76# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
77#endif
78
79void matrix_print(void) {
80 print_matrix_header();
81
82 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
83 print_hex8(row);
84 print(": ");
85 print_matrix_row(row);
86 print("\n");
87 }
88}
89
90#ifdef SPLIT_KEYBOARD
91bool matrix_post_scan(void) {
92 bool changed = false;
93 if (is_keyboard_master()) {
94 static bool last_connected = false;
95 matrix_row_t slave_matrix[MATRIX_ROWS_PER_HAND] = {0};
96 if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
97 changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
98
99 last_connected = true;
100 } else if (last_connected) {
101 // reset other half when disconnected
102 memset(slave_matrix, 0, sizeof(slave_matrix));
103 changed = true;
104
105 last_connected = false;
106 }
107
108 if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
109
110 matrix_scan_kb();
111 } else {
112 transport_slave(matrix + thatHand, matrix + thisHand);
113
114 matrix_slave_scan_kb();
115 }
116
117 return changed;
118}
119#endif
120
121/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
122__attribute__((weak)) void matrix_io_delay(void) {
123 wait_us(MATRIX_IO_DELAY);
124}
125__attribute__((weak)) void matrix_output_select_delay(void) {
126 waitInputPinDelay();
127}
128__attribute__((weak)) void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
129 matrix_io_delay();
130}
131
132// CUSTOM MATRIX 'LITE'
133__attribute__((weak)) void matrix_init_custom(void) {}
134__attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) {
135 return true;
136}
137
138#ifdef SPLIT_KEYBOARD
139__attribute__((weak)) void matrix_slave_scan_kb(void) {
140 matrix_slave_scan_user();
141}
142__attribute__((weak)) void matrix_slave_scan_user(void) {}
143#endif
144
145__attribute__((weak)) void matrix_init(void) {
146#ifdef SPLIT_KEYBOARD
147 thisHand = isLeftHand ? 0 : (MATRIX_ROWS_PER_HAND);
148 thatHand = MATRIX_ROWS_PER_HAND - thisHand;
149#endif
150
151 matrix_init_custom();
152
153 // initialize matrix state: all keys off
154 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
155 raw_matrix[i] = 0;
156 matrix[i] = 0;
157 }
158
159 debounce_init();
160
161 matrix_init_kb();
162}
163
164__attribute__((weak)) uint8_t matrix_scan(void) {
165 bool changed = matrix_scan_custom(raw_matrix);
166
167#ifdef SPLIT_KEYBOARD
168 changed = debounce(raw_matrix, matrix + thisHand, changed) | matrix_post_scan();
169#else
170 changed = debounce(raw_matrix, matrix, changed);
171 matrix_scan_kb();
172#endif
173
174 return changed;
175}
176
177__attribute__((weak)) bool peek_matrix(uint8_t row_index, uint8_t col_index, bool raw) {
178 return 0 != ((raw ? raw_matrix[row_index] : matrix[row_index]) & (MATRIX_ROW_SHIFTER << col_index));
179}