aboutsummaryrefslogtreecommitdiff
path: root/quantum/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r--quantum/matrix.c274
1 files changed, 211 insertions, 63 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 34d6af2e6..ed4643f81 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 < MATRIX_ROWS; 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);
@@ -118,79 +184,109 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_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(); // 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 < MATRIX_ROWS; 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;
150
151 // Select col 225 // Select col
152 select_col(current_col); 226 if (!select_col(current_col)) { // select col
227 return; // skip NO_PIN col
228 }
153 matrix_output_select_delay(); 229 matrix_output_select_delay();
154 230
155 // For each row... 231 // For each row...
156 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 232 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 233 // Check row pin state
162 if (readPin(row_pins[row_index]) == 0) { 234 if (readMatrixPin(row_pins[row_index]) == 0) {
163 // Pin LO, set col bit 235 // Pin LO, set col bit
164 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 236 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
165 } else { 237 } else {
166 // Pin HI, clear col bit 238 // Pin HI, clear col bit
167 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 239 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 } 240 }
175 } 241 }
176 242
177 // Unselect col 243 // Unselect col
178 unselect_col(current_col); 244 unselect_col(current_col);
179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 245 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
180
181 return matrix_changed;
182} 246}
183 247
184# else 248# else
185# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 249# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
186# endif 250# endif
251# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
187#else 252#else
188# error DIODE_DIRECTION is not defined! 253# error DIODE_DIRECTION is not defined!
189#endif 254#endif
190 255
191void matrix_init(void) { 256void matrix_init(void) {
257#ifdef SPLIT_KEYBOARD
258 split_pre_init();
259
260 // Set pinout for right half if pinout for that half is defined
261 if (!isLeftHand) {
262# ifdef DIRECT_PINS_RIGHT
263 const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT;
264 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
265 for (uint8_t j = 0; j < MATRIX_COLS; j++) {
266 direct_pins[i][j] = direct_pins_right[i][j];
267 }
268 }
269# endif
270# ifdef MATRIX_ROW_PINS_RIGHT
271 const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
272 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
273 row_pins[i] = row_pins_right[i];
274 }
275# endif
276# ifdef MATRIX_COL_PINS_RIGHT
277 const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
278 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
279 col_pins[i] = col_pins_right[i];
280 }
281# endif
282 }
283
284 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
285 thatHand = ROWS_PER_HAND - thisHand;
286#endif
287
192 // initialize key pins 288 // initialize key pins
193 init_pins(); 289 matrix_init_pins();
194 290
195 // initialize matrix state: all keys off 291 // initialize matrix state: all keys off
196 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 292 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -198,28 +294,80 @@ void matrix_init(void) {
198 matrix[i] = 0; 294 matrix[i] = 0;
199 } 295 }
200 296
201 debounce_init(MATRIX_ROWS); 297 debounce_init(ROWS_PER_HAND);
202 298
203 matrix_init_quantum(); 299 matrix_init_quantum();
300
301#ifdef SPLIT_KEYBOARD
302 split_post_init();
303#endif
204} 304}
205 305
206uint8_t matrix_scan(void) { 306#ifdef SPLIT_KEYBOARD
307bool matrix_post_scan(void) {
207 bool changed = false; 308 bool changed = false;
309 if (is_keyboard_master()) {
310 static uint8_t error_count;
311
312 matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
313 if (!transport_master(matrix + thisHand, slave_matrix)) {
314 error_count++;
315
316 if (error_count > ERROR_DISCONNECT_COUNT) {
317 // reset other half if disconnected
318 for (int i = 0; i < ROWS_PER_HAND; ++i) {
319 matrix[thatHand + i] = 0;
320 slave_matrix[i] = 0;
321 }
322
323 changed = true;
324 }
325 } else {
326 error_count = 0;
327
328 for (int i = 0; i < ROWS_PER_HAND; ++i) {
329 if (matrix[thatHand + i] != slave_matrix[i]) {
330 matrix[thatHand + i] = slave_matrix[i];
331 changed = true;
332 }
333 }
334 }
335
336 matrix_scan_quantum();
337 } else {
338 transport_slave(matrix + thatHand, matrix + thisHand);
339
340 matrix_slave_scan_kb();
341 }
342
343 return changed;
344}
345#endif
346
347uint8_t matrix_scan(void) {
348 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
208 349
209#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 350#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
210 // Set row, read cols 351 // Set row, read cols
211 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 352 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
212 changed |= read_cols_on_row(raw_matrix, current_row); 353 matrix_read_cols_on_row(curr_matrix, current_row);
213 } 354 }
214#elif (DIODE_DIRECTION == ROW2COL) 355#elif (DIODE_DIRECTION == ROW2COL)
215 // Set col, read rows 356 // Set col, read rows
216 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 357 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
217 changed |= read_rows_on_col(raw_matrix, current_col); 358 matrix_read_rows_on_col(curr_matrix, current_col);
218 } 359 }
219#endif 360#endif
220 361
221 debounce(raw_matrix, matrix, MATRIX_ROWS, changed); 362 bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
363 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
222 364
365#ifdef SPLIT_KEYBOARD
366 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
367 changed = (changed || matrix_post_scan());
368#else
369 debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
223 matrix_scan_quantum(); 370 matrix_scan_quantum();
371#endif
224 return (uint8_t)changed; 372 return (uint8_t)changed;
225} 373}