2 Copyright 2012 Jun Wako <wakojun@gmail.com>
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "split_util.h"
29 #include "split_flags.h"
32 #ifdef BACKLIGHT_ENABLE
33 # include "backlight.h"
34 extern backlight_config_t backlight_config;
37 #if defined(USE_I2C) || defined(EH)
43 #ifndef DEBOUNCING_DELAY
44 # define DEBOUNCING_DELAY 5
47 #if (DEBOUNCING_DELAY > 0)
48 static uint16_t debouncing_time;
49 static bool debouncing = false;
52 #if defined(USE_I2C) || defined(EH)
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)
60 # error "Currently only supports 8 COLS"
65 #if (MATRIX_COLS <= 8)
66 # define print_matrix_header() print("\nr/c 01234567\n")
67 # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
68 # define matrix_bitpop(i) bitpop(matrix[i])
69 # define ROW_SHIFTER ((uint8_t)1)
70 #elif (MATRIX_COLS <= 16)
71 # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
72 # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
73 # define matrix_bitpop(i) bitpop16(matrix[i])
74 # define ROW_SHIFTER ((uint16_t)1)
75 #elif (MATRIX_COLS <= 32)
76 # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
77 # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
78 # define matrix_bitpop(i) bitpop32(matrix[i])
79 # define ROW_SHIFTER ((uint32_t)1)
83 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
85 #define ERROR_DISCONNECT_COUNT 5
87 #define ROWS_PER_HAND (MATRIX_ROWS/2)
89 static uint8_t error_count = 0;
91 static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
92 static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
94 /* matrix state(1:on, 0:off) */
95 static matrix_row_t matrix[MATRIX_ROWS];
96 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
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);
112 __attribute__ ((weak))
113 void matrix_init_kb(void) {
117 __attribute__ ((weak))
118 void matrix_scan_kb(void) {
122 __attribute__ ((weak))
123 void matrix_init_user(void) {
126 __attribute__ ((weak))
127 void matrix_scan_user(void) {
130 __attribute__ ((weak))
131 void matrix_slave_scan_user(void) {
135 uint8_t matrix_rows(void)
141 uint8_t matrix_cols(void)
146 void matrix_init(void)
152 // Set pinout for right half if pinout for that half is defined
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];
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];
166 // initialize row and col
167 #if (DIODE_DIRECTION == COL2ROW)
170 #elif (DIODE_DIRECTION == ROW2COL)
175 // initialize matrix state: all keys off
176 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
178 matrix_debouncing[i] = 0;
181 matrix_init_quantum();
185 uint8_t _matrix_scan(void)
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);
194 if (matrix_changed) {
196 debouncing_time = timer_read();
200 read_cols_on_row(matrix+offset, current_row);
205 #elif (DIODE_DIRECTION == ROW2COL)
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) {
212 debouncing_time = timer_read();
215 read_rows_on_col(matrix+offset, current_col);
221 # if (DEBOUNCING_DELAY > 0)
222 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
223 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
224 matrix[i+offset] = matrix_debouncing[i+offset];
233 #if defined(USE_I2C) || defined(EH)
235 // Get rows from other half over i2c
236 int i2c_transaction(void) {
237 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
240 // write backlight info
241 #ifdef BACKLIGHT_ENABLE
243 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
244 if (err) goto i2c_error;
246 // Backlight location
247 err = i2c_master_write(I2C_BACKLIT_START);
248 if (err) goto i2c_error;
251 i2c_master_write(get_backlight_level());
253 BACKLIT_DIRTY = false;
257 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
258 if (err) goto i2c_error;
260 // start of matrix stored at I2C_KEYMAP_START
261 err = i2c_master_write(I2C_KEYMAP_START);
262 if (err) goto i2c_error;
265 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
266 if (err) goto i2c_error;
270 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
271 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
273 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
276 i2c_error: // the cable is disconnceted, or something else went wrong
281 #ifdef RGBLIGHT_ENABLE
283 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
284 if (err) goto i2c_error;
287 err = i2c_master_write(I2C_RGB_START);
288 if (err) goto i2c_error;
290 uint32_t dword = eeconfig_read_rgblight();
293 err = i2c_master_write_data(&dword, 4);
294 if (err) goto i2c_error;
307 typedef struct _Serial_s2m_buffer_t {
308 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
309 matrix_row_t smatrix[ROWS_PER_HAND];
310 } Serial_s2m_buffer_t;
312 volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
313 volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
314 uint8_t volatile status0 = 0;
316 SSTD_t transactions[] = {
317 { (uint8_t *)&status0,
318 sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
319 sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
323 void serial_master_init(void)
324 { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
326 void serial_slave_init(void)
327 { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
329 int serial_transaction(void) {
330 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
332 if (soft_serial_transaction()) {
336 // TODO: if MATRIX_COLS > 8 change to unpack()
337 for (int i = 0; i < ROWS_PER_HAND; ++i) {
338 matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i];
341 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
342 // Code to send RGB over serial goes here (not implemented yet)
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;
354 uint8_t matrix_scan(void)
356 uint8_t ret = _matrix_scan();
358 #if defined(USE_I2C) || defined(EH)
359 if( i2c_transaction() ) {
361 if( serial_transaction() ) {
366 if (error_count > ERROR_DISCONNECT_COUNT) {
367 // reset other half if disconnected
368 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
369 for (int i = 0; i < ROWS_PER_HAND; ++i) {
370 matrix[slaveOffset+i] = 0;
376 matrix_scan_quantum();
380 void matrix_slave_scan(void) {
383 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
385 #if defined(USE_I2C) || defined(EH)
386 for (int i = 0; i < ROWS_PER_HAND; ++i) {
387 i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
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];
395 matrix_slave_scan_user();
398 bool matrix_is_modified(void)
400 if (debouncing) return false;
405 bool matrix_is_on(uint8_t row, uint8_t col)
407 return (matrix[row] & ((matrix_row_t)1<<col));
411 matrix_row_t matrix_get_row(uint8_t row)
416 void matrix_print(void)
418 print("\nr/c 0123456789ABCDEF\n");
419 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
420 phex(row); print(": ");
421 pbin_reverse16(matrix_get_row(row));
426 uint8_t matrix_key_count(void)
429 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
430 count += bitpop16(matrix[i]);
435 #if (DIODE_DIRECTION == COL2ROW)
437 static void init_cols(void)
439 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
440 setPinInputHigh(col_pins[x]);
444 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
446 // Store last value of row prior to reading
447 matrix_row_t last_row_value = current_matrix[current_row];
449 // Clear data in matrix row
450 current_matrix[current_row] = 0;
452 // Select row and wait for row selecton to stabilize
453 select_row(current_row);
457 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
458 // Populate the matrix row with the state of the col pin
459 current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
463 unselect_row(current_row);
465 return (last_row_value != current_matrix[current_row]);
468 static void select_row(uint8_t row)
470 writePinLow(row_pins[row]);
471 setPinOutput(row_pins[row]);
474 static void unselect_row(uint8_t row)
476 setPinInputHigh(row_pins[row]);
479 static void unselect_rows(void)
481 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
482 setPinInputHigh(row_pins[x]);
486 #elif (DIODE_DIRECTION == ROW2COL)
488 static void init_rows(void)
490 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
491 setPinInputHigh(row_pins[x]);
495 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
497 bool matrix_changed = false;
499 // Select col and wait for col selecton to stabilize
500 select_col(current_col);
504 for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
507 // Store last value of row prior to reading
508 matrix_row_t last_row_value = current_matrix[row_index];
510 // Check row pin state
511 if (readPin(row_pins[row_index]))
513 // Pin HI, clear col bit
514 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
518 // Pin LO, set col bit
519 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
522 // Determine if the matrix changed state
523 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
525 matrix_changed = true;
530 unselect_col(current_col);
532 return matrix_changed;
535 static void select_col(uint8_t col)
537 writePinLow(col_pins[col]);
538 setPinOutput(col_pins[col]);
541 static void unselect_col(uint8_t col)
543 setPinInputHigh(col_pins[col]);
546 static void unselect_cols(void)
548 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
549 setPinInputHigh(col_pins[x]);