aboutsummaryrefslogtreecommitdiff
path: root/quantum/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r--quantum/matrix.c331
1 files changed, 223 insertions, 108 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 3174e0739..5337e2626 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -1,6 +1,5 @@
1/* 1/*
2Copyright 2012 Jun Wako 2Copyright 2012-2017 Jun Wako, Jack Humbert
3Copyright 2014 Jack Humbert
4 3
5This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
@@ -25,37 +24,66 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
25#include "debug.h" 24#include "debug.h"
26#include "util.h" 25#include "util.h"
27#include "matrix.h" 26#include "matrix.h"
27#include "timer.h"
28
28 29
29/* Set 0 if debouncing isn't needed */ 30/* Set 0 if debouncing isn't needed */
30 31
31#ifndef DEBOUNCING_DELAY 32#ifndef DEBOUNCING_DELAY
32# define DEBOUNCING_DELAY 5 33# define DEBOUNCING_DELAY 5
33#endif 34#endif
34static uint8_t debouncing = DEBOUNCING_DELAY;
35 35
36#if (DEBOUNCING_DELAY > 0)
37 static uint16_t debouncing_time;
38 static bool debouncing = false;
39#endif
40
41#if (MATRIX_COLS <= 8)
42# define print_matrix_header() print("\nr/c 01234567\n")
43# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
44# define matrix_bitpop(i) bitpop(matrix[i])
45# define ROW_SHIFTER ((uint8_t)1)
46#elif (MATRIX_COLS <= 16)
47# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
48# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
49# define matrix_bitpop(i) bitpop16(matrix[i])
50# define ROW_SHIFTER ((uint16_t)1)
51#elif (MATRIX_COLS <= 32)
52# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
53# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
54# define matrix_bitpop(i) bitpop32(matrix[i])
55# define ROW_SHIFTER ((uint32_t)1)
56#endif
57
58#ifdef MATRIX_MASKED
59 extern const matrix_row_t matrix_mask[];
60#endif
61
62#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
36static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 63static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
37static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 64static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
65#endif
38 66
39/* matrix state(1:on, 0:off) */ 67/* matrix state(1:on, 0:off) */
40static matrix_row_t matrix[MATRIX_ROWS]; 68static matrix_row_t matrix[MATRIX_ROWS];
69
41static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 70static matrix_row_t matrix_debouncing[MATRIX_ROWS];
42 71
43#if DIODE_DIRECTION == ROW2COL
44 static matrix_row_t matrix_reversed[MATRIX_COLS];
45 static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
46#endif
47 72
48#if MATRIX_COLS > 16 73#if (DIODE_DIRECTION == COL2ROW)
49 #define SHIFTER 1UL 74 static void init_cols(void);
50#else 75 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
51 #define SHIFTER 1 76 static void unselect_rows(void);
77 static void select_row(uint8_t row);
78 static void unselect_row(uint8_t row);
79#elif (DIODE_DIRECTION == ROW2COL)
80 static void init_rows(void);
81 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
82 static void unselect_cols(void);
83 static void unselect_col(uint8_t col);
84 static void select_col(uint8_t col);
52#endif 85#endif
53 86
54static matrix_row_t read_cols(void);
55static void init_cols(void);
56static void unselect_rows(void);
57static void select_row(uint8_t row);
58
59__attribute__ ((weak)) 87__attribute__ ((weak))
60void matrix_init_quantum(void) { 88void matrix_init_quantum(void) {
61 matrix_init_kb(); 89 matrix_init_kb();
@@ -95,7 +123,7 @@ uint8_t matrix_cols(void) {
95} 123}
96 124
97// void matrix_power_up(void) { 125// void matrix_power_up(void) {
98// #if DIODE_DIRECTION == COL2ROW 126// #if (DIODE_DIRECTION == COL2ROW)
99// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { 127// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
100// /* DDRxn */ 128// /* DDRxn */
101// _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); 129// _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
@@ -105,7 +133,7 @@ uint8_t matrix_cols(void) {
105// /* PORTxn */ 133// /* PORTxn */
106// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); 134// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
107// } 135// }
108// #else 136// #elif (DIODE_DIRECTION == ROW2COL)
109// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 137// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
110// /* DDRxn */ 138// /* DDRxn */
111// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); 139// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
@@ -119,15 +147,21 @@ uint8_t matrix_cols(void) {
119// } 147// }
120 148
121void matrix_init(void) { 149void matrix_init(void) {
150
122 // To use PORTF disable JTAG with writing JTD bit twice within four cycles. 151 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
123 #ifdef __AVR_ATmega32U4__ 152 #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
124 MCUCR |= _BV(JTD); 153 MCUCR |= _BV(JTD);
125 MCUCR |= _BV(JTD); 154 MCUCR |= _BV(JTD);
126 #endif 155 #endif
127 156
128 // initialize row and col 157 // initialize row and col
158#if (DIODE_DIRECTION == COL2ROW)
129 unselect_rows(); 159 unselect_rows();
130 init_cols(); 160 init_cols();
161#elif (DIODE_DIRECTION == ROW2COL)
162 unselect_cols();
163 init_rows();
164#endif
131 165
132 // initialize matrix state: all keys off 166 // initialize matrix state: all keys off
133 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 167 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
@@ -141,71 +175,60 @@ void matrix_init(void) {
141uint8_t matrix_scan(void) 175uint8_t matrix_scan(void)
142{ 176{
143 177
144#if DIODE_DIRECTION == COL2ROW 178#if (DIODE_DIRECTION == COL2ROW)
145 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
146 select_row(i);
147 wait_us(30); // without this wait read unstable value.
148 matrix_row_t cols = read_cols();
149 if (matrix_debouncing[i] != cols) {
150 matrix_debouncing[i] = cols;
151 if (debouncing) {
152 debug("bounce!: "); debug_hex(debouncing); debug("\n");
153 }
154 debouncing = DEBOUNCING_DELAY;
155 }
156 unselect_rows();
157 }
158 179
159 if (debouncing) { 180 // Set row, read cols
160 if (--debouncing) { 181 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
161 wait_ms(1); 182# if (DEBOUNCING_DELAY > 0)
162 } else { 183 bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
163 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 184
164 matrix[i] = matrix_debouncing[i]; 185 if (matrix_changed) {
186 debouncing = true;
187 debouncing_time = timer_read();
165 } 188 }
166 } 189
190# else
191 read_cols_on_row(matrix, current_row);
192# endif
193
167 } 194 }
168#else 195
169 for (uint8_t i = 0; i < MATRIX_COLS; i++) { 196#elif (DIODE_DIRECTION == ROW2COL)
170 select_row(i); 197
171 wait_us(30); // without this wait read unstable value. 198 // Set col, read rows
172 matrix_row_t rows = read_cols(); 199 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
173 if (matrix_reversed_debouncing[i] != rows) { 200# if (DEBOUNCING_DELAY > 0)
174 matrix_reversed_debouncing[i] = rows; 201 bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
175 if (debouncing) { 202 if (matrix_changed) {
176 debug("bounce!: "); debug_hex(debouncing); debug("\n"); 203 debouncing = true;
204 debouncing_time = timer_read();
177 } 205 }
178 debouncing = DEBOUNCING_DELAY; 206# else
179 } 207 read_rows_on_col(matrix, current_col);
180 unselect_rows(); 208# endif
209
181 } 210 }
182 211
183 if (debouncing) { 212#endif
184 if (--debouncing) { 213
185 wait_ms(1); 214# if (DEBOUNCING_DELAY > 0)
186 } else { 215 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
187 for (uint8_t i = 0; i < MATRIX_COLS; i++) { 216 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
188 matrix_reversed[i] = matrix_reversed_debouncing[i]; 217 matrix[i] = matrix_debouncing[i];
189 } 218 }
219 debouncing = false;
190 } 220 }
191 } 221# endif
192 for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
193 matrix_row_t row = 0;
194 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
195 row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
196 }
197 matrix[y] = row;
198 }
199#endif
200 222
201 matrix_scan_quantum(); 223 matrix_scan_quantum();
202
203 return 1; 224 return 1;
204} 225}
205 226
206bool matrix_is_modified(void) 227bool matrix_is_modified(void)
207{ 228{
229#if (DEBOUNCING_DELAY > 0)
208 if (debouncing) return false; 230 if (debouncing) return false;
231#endif
209 return true; 232 return true;
210} 233}
211 234
@@ -218,15 +241,22 @@ bool matrix_is_on(uint8_t row, uint8_t col)
218inline 241inline
219matrix_row_t matrix_get_row(uint8_t row) 242matrix_row_t matrix_get_row(uint8_t row)
220{ 243{
244 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
245 // switch blocker installed and the switch is always pressed.
246#ifdef MATRIX_MASKED
247 return matrix[row] & matrix_mask[row];
248#else
221 return matrix[row]; 249 return matrix[row];
250#endif
222} 251}
223 252
224void matrix_print(void) 253void matrix_print(void)
225{ 254{
226 print("\nr/c 0123456789ABCDEF\n"); 255 print_matrix_header();
256
227 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 257 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
228 phex(row); print(": "); 258 phex(row); print(": ");
229 pbin_reverse16(matrix_get_row(row)); 259 print_matrix_row(row);
230 print("\n"); 260 print("\n");
231 } 261 }
232} 262}
@@ -235,63 +265,148 @@ uint8_t matrix_key_count(void)
235{ 265{
236 uint8_t count = 0; 266 uint8_t count = 0;
237 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 267 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
238 count += bitpop16(matrix[i]); 268 count += matrix_bitpop(i);
239 } 269 }
240 return count; 270 return count;
241} 271}
242 272
273
274
275#if (DIODE_DIRECTION == COL2ROW)
276
243static void init_cols(void) 277static void init_cols(void)
244{ 278{
245#if DIODE_DIRECTION == COL2ROW 279 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
246 for(int x = 0; x < MATRIX_COLS; x++) { 280 uint8_t pin = col_pins[x];
247 int pin = col_pins[x]; 281 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
248#else 282 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
249 for(int x = 0; x < MATRIX_ROWS; x++) {
250 int pin = row_pins[x];
251#endif
252 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
253 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
254 } 283 }
255} 284}
256 285
257static matrix_row_t read_cols(void) 286static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
258{ 287{
259 matrix_row_t result = 0; 288 // Store last value of row prior to reading
289 matrix_row_t last_row_value = current_matrix[current_row];
260 290
261#if DIODE_DIRECTION == COL2ROW 291 // Clear data in matrix row
262 for(int x = 0; x < MATRIX_COLS; x++) { 292 current_matrix[current_row] = 0;
263 int pin = col_pins[x]; 293
264#else 294 // Select row and wait for row selecton to stabilize
265 for(int x = 0; x < MATRIX_ROWS; x++) { 295 select_row(current_row);
266 int pin = row_pins[x]; 296 wait_us(30);
267#endif 297
268 result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); 298 // For each col...
299 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
300
301 // Select the col pin to read (active low)
302 uint8_t pin = col_pins[col_index];
303 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
304
305 // Populate the matrix row with the state of the col pin
306 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
269 } 307 }
270 return result; 308
309 // Unselect row
310 unselect_row(current_row);
311
312 return (last_row_value != current_matrix[current_row]);
313}
314
315static void select_row(uint8_t row)
316{
317 uint8_t pin = row_pins[row];
318 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
319 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
320}
321
322static void unselect_row(uint8_t row)
323{
324 uint8_t pin = row_pins[row];
325 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
326 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
271} 327}
272 328
273static void unselect_rows(void) 329static void unselect_rows(void)
274{ 330{
275#if DIODE_DIRECTION == COL2ROW 331 for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
276 for(int x = 0; x < MATRIX_ROWS; x++) { 332 uint8_t pin = row_pins[x];
277 int pin = row_pins[x]; 333 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
278#else 334 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
279 for(int x = 0; x < MATRIX_COLS; x++) {
280 int pin = col_pins[x];
281#endif
282 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
283 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
284 } 335 }
285} 336}
286 337
287static void select_row(uint8_t row) 338#elif (DIODE_DIRECTION == ROW2COL)
339
340static void init_rows(void)
288{ 341{
342 for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
343 uint8_t pin = row_pins[x];
344 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
345 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
346 }
347}
289 348
290#if DIODE_DIRECTION == COL2ROW 349static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
291 int pin = row_pins[row]; 350{
292#else 351 bool matrix_changed = false;
293 int pin = col_pins[row]; 352
294#endif 353 // Select col and wait for col selecton to stabilize
295 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); 354 select_col(current_col);
296 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); 355 wait_us(30);
356
357 // For each row...
358 for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
359 {
360
361 // Store last value of row prior to reading
362 matrix_row_t last_row_value = current_matrix[row_index];
363
364 // Check row pin state
365 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
366 {
367 // Pin LO, set col bit
368 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
369 }
370 else
371 {
372 // Pin HI, clear col bit
373 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
374 }
375
376 // Determine if the matrix changed state
377 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
378 {
379 matrix_changed = true;
380 }
381 }
382
383 // Unselect col
384 unselect_col(current_col);
385
386 return matrix_changed;
297} 387}
388
389static void select_col(uint8_t col)
390{
391 uint8_t pin = col_pins[col];
392 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
393 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
394}
395
396static void unselect_col(uint8_t col)
397{
398 uint8_t pin = col_pins[col];
399 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
400 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
401}
402
403static void unselect_cols(void)
404{
405 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
406 uint8_t pin = col_pins[x];
407 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
408 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
409 }
410}
411
412#endif