aboutsummaryrefslogtreecommitdiff
path: root/quantum/split_common/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/split_common/matrix.c')
-rw-r--r--quantum/split_common/matrix.c147
1 files changed, 89 insertions, 58 deletions
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 039e7d977..d8e078e9b 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -16,23 +16,30 @@ 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"
23#include "split_util.h" 24#include "split_util.h"
24#include "config.h" 25#include "config.h"
25#include "transport.h" 26#include "transactions.h"
26 27
27#define ERROR_DISCONNECT_COUNT 5 28#ifndef ERROR_DISCONNECT_COUNT
29# define ERROR_DISCONNECT_COUNT 5
30#endif // ERROR_DISCONNECT_COUNT
28 31
29#define ROWS_PER_HAND (MATRIX_ROWS / 2) 32#define ROWS_PER_HAND (MATRIX_ROWS / 2)
30 33
31#ifdef DIRECT_PINS 34#ifdef DIRECT_PINS
32static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 35static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
33#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 36#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
37# ifdef MATRIX_ROW_PINS
34static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 38static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
39# endif // MATRIX_ROW_PINS
40# ifdef MATRIX_COL_PINS
35static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 41static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
42# endif // MATRIX_COL_PINS
36#endif 43#endif
37 44
38/* matrix state(1:on, 0:off) */ 45/* matrix state(1:on, 0:off) */
@@ -45,6 +52,9 @@ uint8_t thisHand, thatHand;
45// user-defined overridable functions 52// user-defined overridable functions
46__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } 53__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
47__attribute__((weak)) void matrix_slave_scan_user(void) {} 54__attribute__((weak)) void matrix_slave_scan_user(void) {}
55__attribute__((weak)) void matrix_init_pins(void);
56__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
57__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
48 58
49static inline void setPinOutput_writeLow(pin_t pin) { 59static inline void setPinOutput_writeLow(pin_t pin) {
50 ATOMIC_BLOCK_FORCEON { 60 ATOMIC_BLOCK_FORCEON {
@@ -57,11 +67,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
57 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); } 67 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
58} 68}
59 69
70static inline uint8_t readMatrixPin(pin_t pin) {
71 if (pin != NO_PIN) {
72 return readPin(pin);
73 } else {
74 return 1;
75 }
76}
77
60// matrix code 78// matrix code
61 79
62#ifdef DIRECT_PINS 80#ifdef DIRECT_PINS
63 81
64static void init_pins(void) { 82__attribute__((weak)) void matrix_init_pins(void) {
65 for (int row = 0; row < MATRIX_ROWS; row++) { 83 for (int row = 0; row < MATRIX_ROWS; row++) {
66 for (int col = 0; col < MATRIX_COLS; col++) { 84 for (int col = 0; col < MATRIX_COLS; col++) {
67 pin_t pin = direct_pins[row][col]; 85 pin_t pin = direct_pins[row][col];
@@ -72,7 +90,7 @@ static void init_pins(void) {
72 } 90 }
73} 91}
74 92
75static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 93__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
76 // Start with a clear matrix row 94 // Start with a clear matrix row
77 matrix_row_t current_row_value = 0; 95 matrix_row_t current_row_value = 0;
78 96
@@ -83,46 +101,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
83 } 101 }
84 } 102 }
85 103
86 // If the row has changed, store the row and return the changed flag. 104 // Update the matrix
87 if (current_matrix[current_row] != current_row_value) { 105 current_matrix[current_row] = current_row_value;
88 current_matrix[current_row] = current_row_value;
89 return true;
90 }
91 return false;
92} 106}
93 107
94#elif defined(DIODE_DIRECTION) 108#elif defined(DIODE_DIRECTION)
95# if (DIODE_DIRECTION == COL2ROW) 109# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
110# if (DIODE_DIRECTION == COL2ROW)
96 111
97static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 112static bool select_row(uint8_t row) {
113 pin_t pin = row_pins[row];
114 if (pin != NO_PIN) {
115 setPinOutput_writeLow(pin);
116 return true;
117 }
118 return false;
119}
98 120
99static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } 121static void unselect_row(uint8_t row) {
122 pin_t pin = row_pins[row];
123 if (pin != NO_PIN) {
124 setPinInputHigh_atomic(pin);
125 }
126}
100 127
101static void unselect_rows(void) { 128static void unselect_rows(void) {
102 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { 129 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
103 setPinInputHigh_atomic(row_pins[x]); 130 unselect_row(x);
104 } 131 }
105} 132}
106 133
107static void init_pins(void) { 134__attribute__((weak)) void matrix_init_pins(void) {
108 unselect_rows(); 135 unselect_rows();
109 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 136 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
110 setPinInputHigh_atomic(col_pins[x]); 137 if (col_pins[x] != NO_PIN) {
138 setPinInputHigh_atomic(col_pins[x]);
139 }
111 } 140 }
112} 141}
113 142
114static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 143__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
115 // Start with a clear matrix row 144 // Start with a clear matrix row
116 matrix_row_t current_row_value = 0; 145 matrix_row_t current_row_value = 0;
117 146
118 // Select row 147 if (!select_row(current_row)) { // Select row
119 select_row(current_row); 148 return; // skip NO_PIN row
149 }
120 matrix_output_select_delay(); 150 matrix_output_select_delay();
121 151
122 // For each col... 152 // For each col...
123 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 153 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
124 // Select the col pin to read (active low) 154 uint8_t pin_state = readMatrixPin(col_pins[col_index]);
125 uint8_t pin_state = readPin(col_pins[col_index]);
126 155
127 // Populate the matrix row with the state of the col pin 156 // Populate the matrix row with the state of the col pin
128 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 157 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
@@ -132,72 +161,71 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
132 unselect_row(current_row); 161 unselect_row(current_row);
133 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 162 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
134 163
135 // If the row has changed, store the row and return the changed flag. 164 // Update the matrix
136 if (current_matrix[current_row] != current_row_value) { 165 current_matrix[current_row] = current_row_value;
137 current_matrix[current_row] = current_row_value; 166}
167
168# elif (DIODE_DIRECTION == ROW2COL)
169
170static bool select_col(uint8_t col) {
171 pin_t pin = col_pins[col];
172 if (pin != NO_PIN) {
173 setPinOutput_writeLow(pin);
138 return true; 174 return true;
139 } 175 }
140 return false; 176 return false;
141} 177}
142 178
143# elif (DIODE_DIRECTION == ROW2COL) 179static void unselect_col(uint8_t col) {
144 180 pin_t pin = col_pins[col];
145static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 181 if (pin != NO_PIN) {
146 182 setPinInputHigh_atomic(pin);
147static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } 183 }
184}
148 185
149static void unselect_cols(void) { 186static void unselect_cols(void) {
150 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 187 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
151 setPinInputHigh_atomic(col_pins[x]); 188 unselect_col(x);
152 } 189 }
153} 190}
154 191
155static void init_pins(void) { 192__attribute__((weak)) void matrix_init_pins(void) {
156 unselect_cols(); 193 unselect_cols();
157 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { 194 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
158 setPinInputHigh_atomic(row_pins[x]); 195 if (row_pins[x] != NO_PIN) {
196 setPinInputHigh_atomic(row_pins[x]);
197 }
159 } 198 }
160} 199}
161 200
162static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 201__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
163 bool matrix_changed = false;
164
165 // Select col 202 // Select col
166 select_col(current_col); 203 if (!select_col(current_col)) { // select col
204 return; // skip NO_PIN col
205 }
167 matrix_output_select_delay(); 206 matrix_output_select_delay();
168 207
169 // For each row... 208 // For each row...
170 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { 209 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
171 // Store last value of row prior to reading
172 matrix_row_t last_row_value = current_matrix[row_index];
173 matrix_row_t current_row_value = last_row_value;
174
175 // Check row pin state 210 // Check row pin state
176 if (readPin(row_pins[row_index]) == 0) { 211 if (readMatrixPin(row_pins[row_index]) == 0) {
177 // Pin LO, set col bit 212 // Pin LO, set col bit
178 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 213 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
179 } else { 214 } else {
180 // Pin HI, clear col bit 215 // Pin HI, clear col bit
181 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 216 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
182 }
183
184 // Determine if the matrix changed state
185 if ((last_row_value != current_row_value)) {
186 matrix_changed |= true;
187 current_matrix[row_index] = current_row_value;
188 } 217 }
189 } 218 }
190 219
191 // Unselect col 220 // Unselect col
192 unselect_col(current_col); 221 unselect_col(current_col);
193 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 222 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
194
195 return matrix_changed;
196} 223}
197 224
198# else 225# else
199# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 226# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
200# endif 227# endif
228# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
201#else 229#else
202# error DIODE_DIRECTION is not defined! 230# error DIODE_DIRECTION is not defined!
203#endif 231#endif
@@ -233,7 +261,7 @@ void matrix_init(void) {
233 thatHand = ROWS_PER_HAND - thisHand; 261 thatHand = ROWS_PER_HAND - thisHand;
234 262
235 // initialize key pins 263 // initialize key pins
236 init_pins(); 264 matrix_init_pins();
237 265
238 // initialize matrix state: all keys off 266 // initialize matrix state: all keys off
239 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 267 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -288,20 +316,23 @@ bool matrix_post_scan(void) {
288} 316}
289 317
290uint8_t matrix_scan(void) { 318uint8_t matrix_scan(void) {
291 bool local_changed = false; 319 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
292 320
293#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 321#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
294 // Set row, read cols 322 // Set row, read cols
295 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { 323 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
296 local_changed |= read_cols_on_row(raw_matrix, current_row); 324 matrix_read_cols_on_row(curr_matrix, current_row);
297 } 325 }
298#elif (DIODE_DIRECTION == ROW2COL) 326#elif (DIODE_DIRECTION == ROW2COL)
299 // Set col, read rows 327 // Set col, read rows
300 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 328 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
301 local_changed |= read_rows_on_col(raw_matrix, current_col); 329 matrix_read_rows_on_col(curr_matrix, current_col);
302 } 330 }
303#endif 331#endif
304 332
333 bool local_changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
334 if (local_changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
335
305 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); 336 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);
306 337
307 bool remote_changed = matrix_post_scan(); 338 bool remote_changed = matrix_post_scan();