aboutsummaryrefslogtreecommitdiff
path: root/quantum/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r--quantum/matrix.c283
1 files changed, 217 insertions, 66 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 34d6af2e6..d22817bf4 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -16,22 +16,69 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <string.h>
19#include "util.h" 20#include "util.h"
20#include "matrix.h" 21#include "matrix.h"
21#include "debounce.h" 22#include "debounce.h"
22#include "quantum.h" 23#include "quantum.h"
24#ifdef SPLIT_KEYBOARD
25# include "split_common/split_util.h"
26# include "split_common/transactions.h"
27
28# ifndef ERROR_DISCONNECT_COUNT
29# define ERROR_DISCONNECT_COUNT 5
30# endif // ERROR_DISCONNECT_COUNT
31
32# define ROWS_PER_HAND (MATRIX_ROWS / 2)
33#else
34# define ROWS_PER_HAND (MATRIX_ROWS)
35#endif
36
37#ifdef DIRECT_PINS_RIGHT
38# define SPLIT_MUTABLE
39#else
40# define SPLIT_MUTABLE const
41#endif
42#ifdef MATRIX_ROW_PINS_RIGHT
43# define SPLIT_MUTABLE_ROW
44#else
45# define SPLIT_MUTABLE_ROW const
46#endif
47#ifdef MATRIX_COL_PINS_RIGHT
48# define SPLIT_MUTABLE_COL
49#else
50# define SPLIT_MUTABLE_COL const
51#endif
23 52
24#ifdef DIRECT_PINS 53#ifdef DIRECT_PINS
25static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 54static SPLIT_MUTABLE pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
26#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 55#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
27static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 56# ifdef MATRIX_ROW_PINS
28static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 57static SPLIT_MUTABLE_ROW pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
58# endif // MATRIX_ROW_PINS
59# ifdef MATRIX_COL_PINS
60static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
61# endif // MATRIX_COL_PINS
29#endif 62#endif
30 63
31/* matrix state(1:on, 0:off) */ 64/* matrix state(1:on, 0:off) */
32extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 65extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
33extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 66extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
34 67
68#ifdef SPLIT_KEYBOARD
69// row offsets for each hand
70uint8_t thisHand, thatHand;
71#endif
72
73// user-defined overridable functions
74__attribute__((weak)) void matrix_init_pins(void);
75__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
76__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
77#ifdef SPLIT_KEYBOARD
78__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
79__attribute__((weak)) void matrix_slave_scan_user(void) {}
80#endif
81
35static inline void setPinOutput_writeLow(pin_t pin) { 82static inline void setPinOutput_writeLow(pin_t pin) {
36 ATOMIC_BLOCK_FORCEON { 83 ATOMIC_BLOCK_FORCEON {
37 setPinOutput(pin); 84 setPinOutput(pin);
@@ -43,11 +90,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
43 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); } 90 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
44} 91}
45 92
93static inline uint8_t readMatrixPin(pin_t pin) {
94 if (pin != NO_PIN) {
95 return readPin(pin);
96 } else {
97 return 1;
98 }
99}
100
46// matrix code 101// matrix code
47 102
48#ifdef DIRECT_PINS 103#ifdef DIRECT_PINS
49 104
50static void init_pins(void) { 105__attribute__((weak)) void matrix_init_pins(void) {
51 for (int row = 0; row < MATRIX_ROWS; row++) { 106 for (int row = 0; row < MATRIX_ROWS; row++) {
52 for (int col = 0; col < MATRIX_COLS; col++) { 107 for (int col = 0; col < MATRIX_COLS; col++) {
53 pin_t pin = direct_pins[row][col]; 108 pin_t pin = direct_pins[row][col];
@@ -58,7 +113,7 @@ static void init_pins(void) {
58 } 113 }
59} 114}
60 115
61static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 116__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
62 // Start with a clear matrix row 117 // Start with a clear matrix row
63 matrix_row_t current_row_value = 0; 118 matrix_row_t current_row_value = 0;
64 119
@@ -69,46 +124,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
69 } 124 }
70 } 125 }
71 126
72 // If the row has changed, store the row and return the changed flag. 127 // Update the matrix
73 if (current_matrix[current_row] != current_row_value) { 128 current_matrix[current_row] = current_row_value;
74 current_matrix[current_row] = current_row_value;
75 return true;
76 }
77 return false;
78} 129}
79 130
80#elif defined(DIODE_DIRECTION) 131#elif defined(DIODE_DIRECTION)
81# if (DIODE_DIRECTION == COL2ROW) 132# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
133# if (DIODE_DIRECTION == COL2ROW)
82 134
83static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 135static bool select_row(uint8_t row) {
136 pin_t pin = row_pins[row];
137 if (pin != NO_PIN) {
138 setPinOutput_writeLow(pin);
139 return true;
140 }
141 return false;
142}
84 143
85static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } 144static void unselect_row(uint8_t row) {
145 pin_t pin = row_pins[row];
146 if (pin != NO_PIN) {
147 setPinInputHigh_atomic(pin);
148 }
149}
86 150
87static void unselect_rows(void) { 151static void unselect_rows(void) {
88 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 152 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
89 setPinInputHigh_atomic(row_pins[x]); 153 unselect_row(x);
90 } 154 }
91} 155}
92 156
93static void init_pins(void) { 157__attribute__((weak)) void matrix_init_pins(void) {
94 unselect_rows(); 158 unselect_rows();
95 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 159 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
96 setPinInputHigh_atomic(col_pins[x]); 160 if (col_pins[x] != NO_PIN) {
161 setPinInputHigh_atomic(col_pins[x]);
162 }
97 } 163 }
98} 164}
99 165
100static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 166__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
101 // Start with a clear matrix row 167 // Start with a clear matrix row
102 matrix_row_t current_row_value = 0; 168 matrix_row_t current_row_value = 0;
103 169
104 // Select row 170 if (!select_row(current_row)) { // Select row
105 select_row(current_row); 171 return; // skip NO_PIN row
172 }
106 matrix_output_select_delay(); 173 matrix_output_select_delay();
107 174
108 // For each col... 175 // For each col...
109 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 176 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
110 // Select the col pin to read (active low) 177 uint8_t pin_state = readMatrixPin(col_pins[col_index]);
111 uint8_t pin_state = readPin(col_pins[col_index]);
112 178
113 // Populate the matrix row with the state of the col pin 179 // Populate the matrix row with the state of the col pin
114 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 180 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
@@ -116,81 +182,114 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
116 182
117 // Unselect row 183 // Unselect row
118 unselect_row(current_row); 184 unselect_row(current_row);
119 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 185 matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH
120 186
121 // If the row has changed, store the row and return the changed flag. 187 // Update the matrix
122 if (current_matrix[current_row] != current_row_value) { 188 current_matrix[current_row] = current_row_value;
123 current_matrix[current_row] = current_row_value; 189}
190
191# elif (DIODE_DIRECTION == ROW2COL)
192
193static bool select_col(uint8_t col) {
194 pin_t pin = col_pins[col];
195 if (pin != NO_PIN) {
196 setPinOutput_writeLow(pin);
124 return true; 197 return true;
125 } 198 }
126 return false; 199 return false;
127} 200}
128 201
129# elif (DIODE_DIRECTION == ROW2COL) 202static void unselect_col(uint8_t col) {
130 203 pin_t pin = col_pins[col];
131static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 204 if (pin != NO_PIN) {
132 205 setPinInputHigh_atomic(pin);
133static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } 206 }
207}
134 208
135static void unselect_cols(void) { 209static void unselect_cols(void) {
136 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 210 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
137 setPinInputHigh_atomic(col_pins[x]); 211 unselect_col(x);
138 } 212 }
139} 213}
140 214
141static void init_pins(void) { 215__attribute__((weak)) void matrix_init_pins(void) {
142 unselect_cols(); 216 unselect_cols();
143 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 217 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
144 setPinInputHigh_atomic(row_pins[x]); 218 if (row_pins[x] != NO_PIN) {
219 setPinInputHigh_atomic(row_pins[x]);
220 }
145 } 221 }
146} 222}
147 223
148static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 224__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
149 bool matrix_changed = false; 225 bool key_pressed = false;
150 226
151 // Select col 227 // Select col
152 select_col(current_col); 228 if (!select_col(current_col)) { // select col
229 return; // skip NO_PIN col
230 }
153 matrix_output_select_delay(); 231 matrix_output_select_delay();
154 232
155 // For each row... 233 // For each row...
156 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 234 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
157 // Store last value of row prior to reading
158 matrix_row_t last_row_value = current_matrix[row_index];
159 matrix_row_t current_row_value = last_row_value;
160
161 // Check row pin state 235 // Check row pin state
162 if (readPin(row_pins[row_index]) == 0) { 236 if (readMatrixPin(row_pins[row_index]) == 0) {
163 // Pin LO, set col bit 237 // Pin LO, set col bit
164 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 238 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
239 key_pressed = true;
165 } else { 240 } else {
166 // Pin HI, clear col bit 241 // Pin HI, clear col bit
167 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 242 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
168 }
169
170 // Determine if the matrix changed state
171 if ((last_row_value != current_row_value)) {
172 matrix_changed |= true;
173 current_matrix[row_index] = current_row_value;
174 } 243 }
175 } 244 }
176 245
177 // Unselect col 246 // Unselect col
178 unselect_col(current_col); 247 unselect_col(current_col);
179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 248 matrix_output_unselect_delay(current_col, key_pressed); // wait for all Row signals to go HIGH
180
181 return matrix_changed;
182} 249}
183 250
184# else 251# else
185# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 252# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
186# endif 253# endif
254# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
187#else 255#else
188# error DIODE_DIRECTION is not defined! 256# error DIODE_DIRECTION is not defined!
189#endif 257#endif
190 258
191void matrix_init(void) { 259void matrix_init(void) {
260#ifdef SPLIT_KEYBOARD
261 split_pre_init();
262
263 // Set pinout for right half if pinout for that half is defined
264 if (!isLeftHand) {
265# ifdef DIRECT_PINS_RIGHT
266 const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT;
267 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
268 for (uint8_t j = 0; j < MATRIX_COLS; j++) {
269 direct_pins[i][j] = direct_pins_right[i][j];
270 }
271 }
272# endif
273# ifdef MATRIX_ROW_PINS_RIGHT
274 const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
275 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
276 row_pins[i] = row_pins_right[i];
277 }
278# endif
279# ifdef MATRIX_COL_PINS_RIGHT
280 const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
281 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
282 col_pins[i] = col_pins_right[i];
283 }
284# endif
285 }
286
287 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
288 thatHand = ROWS_PER_HAND - thisHand;
289#endif
290
192 // initialize key pins 291 // initialize key pins
193 init_pins(); 292 matrix_init_pins();
194 293
195 // initialize matrix state: all keys off 294 // initialize matrix state: all keys off
196 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 295 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -198,28 +297,80 @@ void matrix_init(void) {
198 matrix[i] = 0; 297 matrix[i] = 0;
199 } 298 }
200 299
201 debounce_init(MATRIX_ROWS); 300 debounce_init(ROWS_PER_HAND);
202 301
203 matrix_init_quantum(); 302 matrix_init_quantum();
303
304#ifdef SPLIT_KEYBOARD
305 split_post_init();
306#endif
204} 307}
205 308
206uint8_t matrix_scan(void) { 309#ifdef SPLIT_KEYBOARD
310bool matrix_post_scan(void) {
207 bool changed = false; 311 bool changed = false;
312 if (is_keyboard_master()) {
313 static uint8_t error_count;
314
315 matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
316 if (!transport_master(matrix + thisHand, slave_matrix)) {
317 error_count++;
318
319 if (error_count > ERROR_DISCONNECT_COUNT) {
320 // reset other half if disconnected
321 for (int i = 0; i < ROWS_PER_HAND; ++i) {
322 matrix[thatHand + i] = 0;
323 slave_matrix[i] = 0;
324 }
325
326 changed = true;
327 }
328 } else {
329 error_count = 0;
330
331 for (int i = 0; i < ROWS_PER_HAND; ++i) {
332 if (matrix[thatHand + i] != slave_matrix[i]) {
333 matrix[thatHand + i] = slave_matrix[i];
334 changed = true;
335 }
336 }
337 }
338
339 matrix_scan_quantum();
340 } else {
341 transport_slave(matrix + thatHand, matrix + thisHand);
342
343 matrix_slave_scan_kb();
344 }
345
346 return changed;
347}
348#endif
349
350uint8_t matrix_scan(void) {
351 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
208 352
209#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 353#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
210 // Set row, read cols 354 // Set row, read cols
211 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 355 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
212 changed |= read_cols_on_row(raw_matrix, current_row); 356 matrix_read_cols_on_row(curr_matrix, current_row);
213 } 357 }
214#elif (DIODE_DIRECTION == ROW2COL) 358#elif (DIODE_DIRECTION == ROW2COL)
215 // Set col, read rows 359 // Set col, read rows
216 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 360 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
217 changed |= read_rows_on_col(raw_matrix, current_col); 361 matrix_read_rows_on_col(curr_matrix, current_col);
218 } 362 }
219#endif 363#endif
220 364
221 debounce(raw_matrix, matrix, MATRIX_ROWS, changed); 365 bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
366 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
222 367
368#ifdef SPLIT_KEYBOARD
369 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
370 changed = (changed || matrix_post_scan());
371#else
372 debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
223 matrix_scan_quantum(); 373 matrix_scan_quantum();
374#endif
224 return (uint8_t)changed; 375 return (uint8_t)changed;
225} 376}