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