aboutsummaryrefslogtreecommitdiff
path: root/quantum/split_common/matrix.c
diff options
context:
space:
mode:
authorJames Churchill <pelrun@gmail.com>2019-01-18 04:08:14 +1000
committerDrashna Jaelre <drashna@live.com>2019-01-17 10:08:14 -0800
commit28929ad0174bdcb38e09f6d272a23b9be6aa430c (patch)
tree3d3568df6a3f7292ccfcedd616cb1bbc8839804c /quantum/split_common/matrix.c
parent5fcca9a226b2ab0b1335396e25c37e4b2a261a06 (diff)
downloadqmk_firmware-28929ad0174bdcb38e09f6d272a23b9be6aa430c.tar.gz
qmk_firmware-28929ad0174bdcb38e09f6d272a23b9be6aa430c.zip
Simplify split_common Code significantly (#4772)
* Eliminate separate slave loop Both master and slave run the standard keyboard_task main loop now. * Refactor i2c/serial specific code Simplify some of the preprocessor mess by using common function names. * Fix missing #endif * Move direct pin mapping support from miniaxe to split_common For boards with more pins than sense--sorry, switches. * Reordering and reformatting only * Don't run matrix_scan_quantum on slave side * Clean up the offset/slaveOffset calculations * Cut undebounced matrix size in half * Refactor debouncing * Minor fixups * Split split_common transport and debounce code into their own files Can now be replaced with custom versions per keyboard using CUSTOM_TRANSPORT = yes and CUSTOM_DEBOUNCE = yes * Refactor debounce for non-split keyboards too * Update handwired/xealous to build using new split_common * Fix debounce breaking basic test * Dodgy method to allow a split kb to only include one of i2c/serial SPLIT_TRANSPORT = serial or SPLIT_TRANSPORT = i2c will include only that driver code in the binary. SPLIT_TRANSPORT = custom (or anything else) will include neither, the keyboard must supply it's own code if SPLIT_TRANSPORT is not defined then the original behaviour (include both avr i2c and serial code) is maintained. This could be better but it would require explicitly updating all the existing split keyboards. * Enable LTO to get lets_split/sockets under the line * Add docs for SPLIT_TRANSPORT, CUSTOM_MATRIX, CUSTOM_DEBOUNCE * Remove avr-specific sei() from split matrix_setup Not needed now that slave doesn't have a separate main loop. Both sides (on avr) call sei() in lufa's main() after exiting keyboard_setup(). * Fix QUANTUM_LIB_SRC references and simplify SPLIT_TRANSPORT. * Add comments and fix formatting.
Diffstat (limited to 'quantum/split_common/matrix.c')
-rw-r--r--quantum/split_common/matrix.c639
1 files changed, 207 insertions, 432 deletions
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 2c37053f8..c3d2857ed 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -25,529 +25,304 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
25#include "matrix.h" 25#include "matrix.h"
26#include "split_util.h" 26#include "split_util.h"
27#include "config.h" 27#include "config.h"
28#include "timer.h"
29#include "split_flags.h" 28#include "split_flags.h"
30#include "quantum.h" 29#include "quantum.h"
31 30#include "debounce.h"
32#ifdef BACKLIGHT_ENABLE 31#include "transport.h"
33# include "backlight.h"
34 extern backlight_config_t backlight_config;
35#endif
36
37#if defined(USE_I2C) || defined(EH)
38# include "i2c.h"
39#else // USE_SERIAL
40# include "serial.h"
41#endif
42
43#ifndef DEBOUNCING_DELAY
44# define DEBOUNCING_DELAY 5
45#endif
46
47#if (DEBOUNCING_DELAY > 0)
48 static uint16_t debouncing_time;
49 static bool debouncing = false;
50#endif
51
52#if defined(USE_I2C) || defined(EH)
53
54#if (MATRIX_COLS <= 8)
55# define print_matrix_header() print("\nr/c 01234567\n")
56# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
57# define matrix_bitpop(i) bitpop(matrix[i])
58# define ROW_SHIFTER ((uint8_t)1)
59#else
60# error "Currently only supports 8 COLS"
61#endif
62
63#else // USE_SERIAL
64 32
65#if (MATRIX_COLS <= 8) 33#if (MATRIX_COLS <= 8)
66# define print_matrix_header() print("\nr/c 01234567\n") 34# define print_matrix_header() print("\nr/c 01234567\n")
67# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) 35# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
68# define matrix_bitpop(i) bitpop(matrix[i]) 36# define matrix_bitpop(i) bitpop(matrix[i])
69# define ROW_SHIFTER ((uint8_t)1) 37# define ROW_SHIFTER ((uint8_t)1)
70#elif (MATRIX_COLS <= 16) 38#elif (MATRIX_COLS <= 16)
71# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") 39# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
72# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) 40# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
73# define matrix_bitpop(i) bitpop16(matrix[i]) 41# define matrix_bitpop(i) bitpop16(matrix[i])
74# define ROW_SHIFTER ((uint16_t)1) 42# define ROW_SHIFTER ((uint16_t)1)
75#elif (MATRIX_COLS <= 32) 43#elif (MATRIX_COLS <= 32)
76# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") 44# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
77# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) 45# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
78# define matrix_bitpop(i) bitpop32(matrix[i]) 46# define matrix_bitpop(i) bitpop32(matrix[i])
79# define ROW_SHIFTER ((uint32_t)1) 47# define ROW_SHIFTER ((uint32_t)1)
80#endif
81
82#endif 48#endif
83static matrix_row_t matrix_debouncing[MATRIX_ROWS];
84 49
85#define ERROR_DISCONNECT_COUNT 5 50#define ERROR_DISCONNECT_COUNT 5
86 51
87#define ROWS_PER_HAND (MATRIX_ROWS/2) 52#define ROWS_PER_HAND (MATRIX_ROWS / 2)
88
89static uint8_t error_count = 0;
90 53
54#ifdef DIRECT_PINS
55static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
56#else
91static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 57static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
92static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 58static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
59#endif
93 60
94/* matrix state(1:on, 0:off) */ 61/* matrix state(1:on, 0:off) */
95static matrix_row_t matrix[MATRIX_ROWS]; 62static matrix_row_t matrix[MATRIX_ROWS];
96static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 63static matrix_row_t raw_matrix[ROWS_PER_HAND];
97
98#if (DIODE_DIRECTION == COL2ROW)
99 static void init_cols(void);
100 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
101 static void unselect_rows(void);
102 static void select_row(uint8_t row);
103 static void unselect_row(uint8_t row);
104#elif (DIODE_DIRECTION == ROW2COL)
105 static void init_rows(void);
106 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
107 static void unselect_cols(void);
108 static void unselect_col(uint8_t col);
109 static void select_col(uint8_t col);
110#endif
111 64
112__attribute__ ((weak)) 65// row offsets for each hand
113void matrix_init_kb(void) { 66uint8_t thisHand, thatHand;
114 matrix_init_user();
115}
116 67
117__attribute__ ((weak)) 68// user-defined overridable functions
118void matrix_scan_kb(void) {
119 matrix_scan_user();
120}
121 69
122__attribute__ ((weak)) 70__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
123void matrix_init_user(void) {
124}
125 71
126__attribute__ ((weak)) 72__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
127void matrix_scan_user(void) {
128}
129 73
130__attribute__ ((weak)) 74__attribute__((weak)) void matrix_init_user(void) {}
131void matrix_slave_scan_user(void) {
132}
133 75
134inline 76__attribute__((weak)) void matrix_scan_user(void) {}
135uint8_t matrix_rows(void)
136{
137 return MATRIX_ROWS;
138}
139 77
140inline 78__attribute__((weak)) void matrix_slave_scan_user(void) {}
141uint8_t matrix_cols(void)
142{
143 return MATRIX_COLS;
144}
145 79
146void matrix_init(void) 80// helper functions
147{
148 debug_enable = true;
149 debug_matrix = true;
150 debug_mouse = true;
151 81
152 // Set pinout for right half if pinout for that half is defined 82inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
153 if (!isLeftHand) {
154#ifdef MATRIX_ROW_PINS_RIGHT
155 const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
156 for (uint8_t i = 0; i < MATRIX_ROWS; i++)
157 row_pins[i] = row_pins_right[i];
158#endif
159#ifdef MATRIX_COL_PINS_RIGHT
160 const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
161 for (uint8_t i = 0; i < MATRIX_COLS; i++)
162 col_pins[i] = col_pins_right[i];
163#endif
164 }
165 83
166 // initialize row and col 84inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
167#if (DIODE_DIRECTION == COL2ROW)
168 unselect_rows();
169 init_cols();
170#elif (DIODE_DIRECTION == ROW2COL)
171 unselect_cols();
172 init_rows();
173#endif
174 85
175 // initialize matrix state: all keys off 86bool matrix_is_modified(void) {
176 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 87 if (debounce_active()) return false;
177 matrix[i] = 0; 88 return true;
178 matrix_debouncing[i] = 0;
179 }
180
181 matrix_init_quantum();
182
183} 89}
184 90
185uint8_t _matrix_scan(void) 91inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
186{
187 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
188#if (DIODE_DIRECTION == COL2ROW)
189 // Set row, read cols
190 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
191# if (DEBOUNCING_DELAY > 0)
192 bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
193
194 if (matrix_changed) {
195 debouncing = true;
196 debouncing_time = timer_read();
197 }
198
199# else
200 read_cols_on_row(matrix+offset, current_row);
201# endif
202
203 }
204 92
205#elif (DIODE_DIRECTION == ROW2COL) 93inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
206 // Set col, read rows
207 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
208# if (DEBOUNCING_DELAY > 0)
209 bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
210 if (matrix_changed) {
211 debouncing = true;
212 debouncing_time = timer_read();
213 }
214# else
215 read_rows_on_col(matrix+offset, current_col);
216# endif
217 94
218 } 95void matrix_print(void) {
219#endif 96 print_matrix_header();
220 97
221# if (DEBOUNCING_DELAY > 0) 98 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
222 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { 99 phex(row);
223 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { 100 print(": ");
224 matrix[i+offset] = matrix_debouncing[i+offset]; 101 print_matrix_row(row);
225 } 102 print("\n");
226 debouncing = false; 103 }
227 } 104}
228# endif
229 105
230 return 1; 106uint8_t matrix_key_count(void) {
107 uint8_t count = 0;
108 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
109 count += matrix_bitpop(i);
110 }
111 return count;
231} 112}
232 113
233#if defined(USE_I2C) || defined(EH) 114// matrix code
234
235// Get rows from other half over i2c
236int i2c_transaction(void) {
237 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
238 int err = 0;
239
240 // write backlight info
241 #ifdef BACKLIGHT_ENABLE
242 if (BACKLIT_DIRTY) {
243 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
244 if (err) goto i2c_error;
245
246 // Backlight location
247 err = i2c_master_write(I2C_BACKLIT_START);
248 if (err) goto i2c_error;
249
250 // Write backlight
251 i2c_master_write(get_backlight_level());
252
253 BACKLIT_DIRTY = false;
254 }
255 #endif
256 115
257 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); 116#ifdef DIRECT_PINS
258 if (err) goto i2c_error;
259 117
260 // start of matrix stored at I2C_KEYMAP_START 118static void init_pins(void) {
261 err = i2c_master_write(I2C_KEYMAP_START); 119 for (int row = 0; row < MATRIX_ROWS; row++) {
262 if (err) goto i2c_error; 120 for (int col = 0; col < MATRIX_COLS; col++) {
121 pin_t pin = direct_pins[row][col];
122 if (pin != NO_PIN) {
123 setPinInputHigh(pin);
124 }
125 }
126 }
127}
263 128
264 // Start read 129static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
265 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); 130 matrix_row_t last_row_value = current_matrix[current_row];
266 if (err) goto i2c_error; 131 current_matrix[current_row] = 0;
267 132
268 if (!err) { 133 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
269 int i; 134 pin_t pin = direct_pins[current_row][col_index];
270 for (i = 0; i < ROWS_PER_HAND-1; ++i) { 135 if (pin != NO_PIN) {
271 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); 136 current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
272 }
273 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
274 i2c_master_stop();
275 } else {
276i2c_error: // the cable is disconnceted, or something else went wrong
277 i2c_reset_state();
278 return err;
279 } 137 }
280 138 }
281 #ifdef RGBLIGHT_ENABLE
282 if (RGB_DIRTY) {
283 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
284 if (err) goto i2c_error;
285
286 // RGB Location
287 err = i2c_master_write(I2C_RGB_START);
288 if (err) goto i2c_error;
289
290 uint32_t dword = eeconfig_read_rgblight();
291
292 // Write RGB
293 err = i2c_master_write_data(&dword, 4);
294 if (err) goto i2c_error;
295
296 RGB_DIRTY = false;
297 i2c_master_stop();
298 }
299 #endif
300 139
301 return 0; 140 return (last_row_value != current_matrix[current_row]);
302} 141}
303 142
304#else // USE_SERIAL 143#elif (DIODE_DIRECTION == COL2ROW)
305
306 144
307typedef struct _Serial_s2m_buffer_t { 145static void select_row(uint8_t row) {
308 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack 146 writePinLow(row_pins[row]);
309 matrix_row_t smatrix[ROWS_PER_HAND]; 147 setPinOutput(row_pins[row]);
310} Serial_s2m_buffer_t; 148}
311 149
312volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; 150static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
313volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
314uint8_t volatile status0 = 0;
315 151
316SSTD_t transactions[] = { 152static void unselect_rows(void) {
317 { (uint8_t *)&status0, 153 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
318 sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, 154 setPinInputHigh(row_pins[x]);
319 sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
320 } 155 }
321}; 156}
322 157
323void serial_master_init(void) 158static void init_pins(void) {
324{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } 159 unselect_rows();
160 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
161 setPinInputHigh(col_pins[x]);
162 }
163}
325 164
326void serial_slave_init(void) 165static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
327{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); } 166 // Store last value of row prior to reading
167 matrix_row_t last_row_value = current_matrix[current_row];
328 168
329int serial_transaction(void) { 169 // Clear data in matrix row
330 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; 170 current_matrix[current_row] = 0;
331 171
332 if (soft_serial_transaction()) { 172 // Select row and wait for row selecton to stabilize
333 return 1; 173 select_row(current_row);
334 } 174 wait_us(30);
335 175
336 // TODO: if MATRIX_COLS > 8 change to unpack() 176 // For each col...
337 for (int i = 0; i < ROWS_PER_HAND; ++i) { 177 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
338 matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i]; 178 // Populate the matrix row with the state of the col pin
339 } 179 current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
340 180 }
341 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
342 // Code to send RGB over serial goes here (not implemented yet)
343 #endif
344
345 #ifdef BACKLIGHT_ENABLE
346 // Write backlight level for slave to read
347 serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
348 #endif
349
350 return 0;
351}
352#endif
353 181
354uint8_t matrix_scan(void) 182 // Unselect row
355{ 183 unselect_row(current_row);
356 uint8_t ret = _matrix_scan();
357 184
358#if defined(USE_I2C) || defined(EH) 185 return (last_row_value != current_matrix[current_row]);
359 if( i2c_transaction() ) { 186}
360#else // USE_SERIAL
361 if( serial_transaction() ) {
362#endif
363 187
364 error_count++; 188#elif (DIODE_DIRECTION == ROW2COL)
365 189
366 if (error_count > ERROR_DISCONNECT_COUNT) { 190static void select_col(uint8_t col) {
367 // reset other half if disconnected 191 writePinLow(col_pins[col]);
368 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; 192 setPinOutput(col_pins[col]);
369 for (int i = 0; i < ROWS_PER_HAND; ++i) {
370 matrix[slaveOffset+i] = 0;
371 }
372 }
373 } else {
374 error_count = 0;
375 }
376 matrix_scan_quantum();
377 return ret;
378} 193}
379 194
380void matrix_slave_scan(void) { 195static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
381 _matrix_scan();
382
383 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
384 196
385#if defined(USE_I2C) || defined(EH) 197static void unselect_cols(void) {
386 for (int i = 0; i < ROWS_PER_HAND; ++i) { 198 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
387 i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i]; 199 setPinInputHigh(col_pins[x]);
388 } 200 }
389#else // USE_SERIAL
390 // TODO: if MATRIX_COLS > 8 change to pack()
391 for (int i = 0; i < ROWS_PER_HAND; ++i) {
392 serial_s2m_buffer.smatrix[i] = matrix[offset+i];
393 }
394#endif
395 matrix_slave_scan_user();
396} 201}
397 202
398bool matrix_is_modified(void) 203static void init_pins(void) {
399{ 204 unselect_cols();
400 if (debouncing) return false; 205 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
401 return true; 206 setPinInputHigh(row_pins[x]);
207 }
402} 208}
403 209
404inline 210static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
405bool matrix_is_on(uint8_t row, uint8_t col) 211 bool matrix_changed = false;
406{
407 return (matrix[row] & ((matrix_row_t)1<<col));
408}
409 212
410inline 213 // Select col and wait for col selecton to stabilize
411matrix_row_t matrix_get_row(uint8_t row) 214 select_col(current_col);
412{ 215 wait_us(30);
413 return matrix[row]; 216
414} 217 // For each row...
218 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
219 // Store last value of row prior to reading
220 matrix_row_t last_row_value = current_matrix[row_index];
415 221
416void matrix_print(void) 222 // Check row pin state
417{ 223 if (readPin(row_pins[row_index])) {
418 print("\nr/c 0123456789ABCDEF\n"); 224 // Pin HI, clear col bit
419 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 225 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
420 phex(row); print(": "); 226 } else {
421 pbin_reverse16(matrix_get_row(row)); 227 // Pin LO, set col bit
422 print("\n"); 228 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
423 } 229 }
424}
425 230
426uint8_t matrix_key_count(void) 231 // Determine if the matrix changed state
427{ 232 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
428 uint8_t count = 0; 233 matrix_changed = true;
429 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
430 count += bitpop16(matrix[i]);
431 } 234 }
432 return count; 235 }
433}
434 236
435#if (DIODE_DIRECTION == COL2ROW) 237 // Unselect col
238 unselect_col(current_col);
436 239
437static void init_cols(void) 240 return matrix_changed;
438{
439 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
440 setPinInputHigh(col_pins[x]);
441 }
442} 241}
443 242
444static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) 243#endif
445{
446 // Store last value of row prior to reading
447 matrix_row_t last_row_value = current_matrix[current_row];
448
449 // Clear data in matrix row
450 current_matrix[current_row] = 0;
451 244
452 // Select row and wait for row selecton to stabilize 245void matrix_init(void) {
453 select_row(current_row); 246 debug_enable = true;
454 wait_us(30); 247 debug_matrix = true;
248 debug_mouse = true;
455 249
456 // For each col... 250 // Set pinout for right half if pinout for that half is defined
457 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 251 if (!isLeftHand) {
458 // Populate the matrix row with the state of the col pin 252#ifdef MATRIX_ROW_PINS_RIGHT
459 current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); 253 const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
254 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
255 row_pins[i] = row_pins_right[i];
460 } 256 }
257#endif
258#ifdef MATRIX_COL_PINS_RIGHT
259 const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
260 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
261 col_pins[i] = col_pins_right[i];
262 }
263#endif
264 }
461 265
462 // Unselect row 266 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
463 unselect_row(current_row); 267 thatHand = ROWS_PER_HAND - thisHand;
464 268
465 return (last_row_value != current_matrix[current_row]); 269 // initialize key pins
466} 270 init_pins();
467 271
468static void select_row(uint8_t row) 272 // initialize matrix state: all keys off
469{ 273 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
470 writePinLow(row_pins[row]); 274 matrix[i] = 0;
471 setPinOutput(row_pins[row]); 275 }
472}
473 276
474static void unselect_row(uint8_t row) 277 debounce_init(ROWS_PER_HAND);
475{
476 setPinInputHigh(row_pins[row]);
477}
478 278
479static void unselect_rows(void) 279 matrix_init_quantum();
480{
481 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
482 setPinInputHigh(row_pins[x]);
483 }
484} 280}
485 281
282uint8_t _matrix_scan(void) {
283 bool changed = false;
284
285#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
286 // Set row, read cols
287 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
288 changed |= read_cols_on_row(raw_matrix, current_row);
289 }
486#elif (DIODE_DIRECTION == ROW2COL) 290#elif (DIODE_DIRECTION == ROW2COL)
291 // Set col, read rows
292 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
293 changed |= read_rows_on_col(raw_matrix, current_col);
294 }
295#endif
487 296
488static void init_rows(void) 297 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
489{
490 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
491 setPinInputHigh(row_pins[x]);
492 }
493}
494 298
495static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) 299 return 1;
496{ 300}
497 bool matrix_changed = false;
498 301
499 // Select col and wait for col selecton to stabilize 302uint8_t matrix_scan(void) {
500 select_col(current_col); 303 uint8_t ret = _matrix_scan();
501 wait_us(30);
502 304
503 // For each row... 305 if (is_keyboard_master()) {
504 for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) 306 static uint8_t error_count;
505 {
506 307
507 // Store last value of row prior to reading 308 if (!transport_master(matrix + thatHand)) {
508 matrix_row_t last_row_value = current_matrix[row_index]; 309 error_count++;
509 310
510 // Check row pin state 311 if (error_count > ERROR_DISCONNECT_COUNT) {
511 if (readPin(row_pins[row_index])) 312 // reset other half if disconnected
512 { 313 for (int i = 0; i < ROWS_PER_HAND; ++i) {
513 // Pin HI, clear col bit 314 matrix[thatHand + i] = 0;
514 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
515 }
516 else
517 {
518 // Pin LO, set col bit
519 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
520 }
521
522 // Determine if the matrix changed state
523 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
524 {
525 matrix_changed = true;
526 } 315 }
316 }
317 } else {
318 error_count = 0;
527 } 319 }
528 320
529 // Unselect col 321 matrix_scan_quantum();
530 unselect_col(current_col); 322 } else {
531 323 transport_slave(matrix + thisHand);
532 return matrix_changed; 324 matrix_slave_scan_user();
533} 325 }
534
535static void select_col(uint8_t col)
536{
537 writePinLow(col_pins[col]);
538 setPinOutput(col_pins[col]);
539}
540
541static void unselect_col(uint8_t col)
542{
543 setPinInputHigh(col_pins[col]);
544}
545 326
546static void unselect_cols(void) 327 return ret;
547{
548 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
549 setPinInputHigh(col_pins[x]);
550 }
551} 328}
552
553#endif