]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/matrix.c
Fixing Debounce - WIP
[qmk_firmware.git] / quantum / matrix.c
1 /*
2 Copyright 2012 Jun Wako
3 Copyright 2014 Jack Humbert
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdint.h>
19 #include <stdbool.h>
20 #if defined(__AVR__)
21 #include <avr/io.h>
22 #endif
23 #include "wait.h"
24 #include "print.h"
25 #include "debug.h"
26 #include "util.h"
27 #include "matrix.h"
28
29 #if (MATRIX_COLS <= 8)
30 #    define print_matrix_header()  print("\nr/c 01234567\n")
31 #    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
32 #    define matrix_bitpop(i)       bitpop(matrix[i])
33 #    define ROW_SHIFTER ((uint8_t)1)
34 #elif (MATRIX_COLS <= 16)
35 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF\n")
36 #    define print_matrix_row(row)  print_bin_reverse16(matrix_get_row(row))
37 #    define matrix_bitpop(i)       bitpop16(matrix[i])
38 #    define ROW_SHIFTER ((uint16_t)1)
39 #elif (MATRIX_COLS <= 32)
40 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
41 #    define print_matrix_row(row)  print_bin_reverse32(matrix_get_row(row))
42 #    define matrix_bitpop(i)       bitpop32(matrix[i])
43 #    define ROW_SHIFTER  ((uint32_t)1)
44 #endif
45
46 #if (MATRIX_ROWS <= 8)
47 #    define COL_SHIFTER ((uint8_t)1)
48 #elif (MATRIX_ROWS <= 16)
49 #    define COL_SHIFTER ((uint16_t)1)
50 #elif (MATRIX_ROWS <= 32)
51 #    define COL_SHIFTER  ((uint32_t)1)
52 #endif
53
54
55
56 #ifdef MATRIX_MASKED
57 extern const matrix_row_t matrix_mask[];
58 #endif
59
60 /* Set 0 if debouncing isn't needed */
61
62 #ifndef DEBOUNCING_DELAY
63 #   define DEBOUNCING_DELAY 5
64 #endif
65 static uint8_t debouncing = DEBOUNCING_DELAY;
66
67 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
68 static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
69
70 /* matrix state(1:on, 0:off) */
71 static matrix_row_t matrix[MATRIX_ROWS];
72
73 #if DIODE_DIRECTION == COL2ROW
74     static matrix_row_t matrix_debouncing[MATRIX_ROWS];
75 #else // ROW2COL
76     static matrix_col_t matrix_transposed[MATRIX_COLS];
77     static matrix_col_t matrix_transposed_debouncing[MATRIX_COLS];
78 #endif
79
80 #if (DIODE_DIRECTION == COL2ROW)
81     static void init_cols(void);
82     static matrix_row_t read_cols(void);
83     static void unselect_rows(void);
84     static void select_row(uint8_t row);
85     static void unselect_row(uint8_t row);
86 #else // ROW2COL
87     static void init_rows(void);
88     static matrix_col_t read_rows(void);
89     static void unselect_cols(void);
90     static void unselect_col(uint8_t col);
91     static void select_col(uint8_t col);
92 #endif
93
94 __attribute__ ((weak))
95 void matrix_init_quantum(void) {
96     matrix_init_kb();
97 }
98
99 __attribute__ ((weak))
100 void matrix_scan_quantum(void) {
101     matrix_scan_kb();
102 }
103
104 __attribute__ ((weak))
105 void matrix_init_kb(void) {
106     matrix_init_user();
107 }
108
109 __attribute__ ((weak))
110 void matrix_scan_kb(void) {
111     matrix_scan_user();
112 }
113
114 __attribute__ ((weak))
115 void matrix_init_user(void) {
116 }
117
118 __attribute__ ((weak))
119 void matrix_scan_user(void) {
120 }
121
122 inline
123 uint8_t matrix_rows(void) {
124     return MATRIX_ROWS;
125 }
126
127 inline
128 uint8_t matrix_cols(void) {
129     return MATRIX_COLS;
130 }
131
132 // void matrix_power_up(void) {
133 // #if (DIODE_DIRECTION == COL2ROW)
134 //     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
135 //         /* DDRxn */
136 //         _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
137 //         toggle_row(r);
138 //     }
139 //     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
140 //         /* PORTxn */
141 //         _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
142 //     }
143 // #else
144 //     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
145 //         /* DDRxn */
146 //         _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
147 //         toggle_col(c);
148 //     }
149 //     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
150 //         /* PORTxn */
151 //         _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
152 //     }
153 // #endif
154 // }
155
156 void matrix_init(void) {
157
158     // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
159     #if  (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
160         MCUCR |= _BV(JTD);
161         MCUCR |= _BV(JTD);
162     #endif
163
164     // initialize row and col
165 #if (DIODE_DIRECTION == COL2ROW)
166     unselect_rows();
167     init_cols();
168
169     // initialize matrix state: all keys off
170     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
171         matrix[i] = 0;
172         matrix_debouncing[i] = 0;
173     }
174
175 #else // ROW2COL
176     unselect_cols();
177     init_rows();
178
179     // initialize matrix state: all keys off
180     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
181         matrix[i] = 0;
182     }
183
184     // initialize matrix state: all keys off
185     for (uint8_t i=0; i < MATRIX_COLS; i++) {
186         matrix_transposed_debouncing[i] = 0;
187     }
188 #endif
189
190     matrix_init_quantum();
191 }
192
193 uint8_t matrix_scan(void)
194 {
195
196 #if (DIODE_DIRECTION == COL2ROW)
197
198     // Set row, read cols
199
200     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
201         select_row(i);
202         wait_us(30);  // without this wait read unstable value.
203         matrix_row_t current_row = read_cols();
204         if (matrix_debouncing[i] != current_row) {
205             matrix_debouncing[i] = current_row;
206             if (debouncing) {
207                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
208             }
209             debouncing = DEBOUNCING_DELAY;
210         }
211         unselect_row(i);
212     }
213
214     if (debouncing) {
215         if (--debouncing) {
216             wait_ms(1);
217         } else {
218             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
219                 matrix[i] = matrix_debouncing[i];
220             }
221         }
222     }
223
224 #else // ROW2COL
225
226     // Set col, read rows
227
228     for (uint8_t i = 0; i < MATRIX_COLS; i++) {
229         select_col(i);
230         wait_us(30);  // without this wait read unstable value.
231         matrix_col_t current_col = read_rows();
232         if (matrix_transposed_debouncing[i] != current_col) {
233             matrix_transposed_debouncing[i] = current_col;
234             if (debouncing) {
235                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
236             }
237             debouncing = DEBOUNCING_DELAY;
238         }
239         unselect_col(i);
240     }
241
242     if (debouncing) {
243         if (--debouncing) {
244             wait_ms(1);
245         } else {
246             for (uint8_t i = 0; i < MATRIX_COLS; i++) {
247                 matrix_transposed[i] = matrix_transposed_debouncing[i];
248             }
249         }
250     }
251
252     // Untranspose matrix
253     for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
254         matrix_row_t row = 0;
255         for (uint8_t x = 0; x < MATRIX_COLS; x++) {
256             row |= ((matrix_transposed[x] & (1<<y)) >> y) << x;
257         }
258         matrix[y] = row;
259     }
260
261 #endif
262
263     matrix_scan_quantum();
264
265     return 1;
266 }
267
268 bool matrix_is_modified(void)
269 {
270     if (debouncing) return false;
271     return true;
272 }
273
274 inline
275 bool matrix_is_on(uint8_t row, uint8_t col)
276 {
277     return (matrix[row] & ((matrix_row_t)1<col));
278 }
279
280 inline
281 matrix_row_t matrix_get_row(uint8_t row)
282 {
283     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
284     // switch blocker installed and the switch is always pressed.
285 #ifdef MATRIX_MASKED
286     return matrix[row] & matrix_mask[row];
287 #else
288     return matrix[row];
289 #endif
290 }
291
292 void matrix_print(void)
293 {
294     print_matrix_header();
295
296     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
297         phex(row); print(": ");
298         print_matrix_row(row);
299         print("\n");
300     }
301 }
302
303 uint8_t matrix_key_count(void)
304 {
305     uint8_t count = 0;
306     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
307         count += matrix_bitpop(i);
308     }
309     return count;
310 }
311
312
313
314 #if (DIODE_DIRECTION == COL2ROW)
315
316 static void init_cols(void)
317 {
318     for(uint8_t x = 0; x < MATRIX_COLS; x++) {
319         uint8_t pin = col_pins[x];
320         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
321         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
322     }
323 }
324
325 static matrix_row_t read_cols(void)
326 {
327     matrix_row_t result = 0;
328
329     for(uint8_t x = 0; x < MATRIX_COLS; x++) {
330         uint8_t pin = col_pins[x];
331         result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (ROW_SHIFTER << x);
332     }
333
334     return result;
335 }
336
337 static void select_row(uint8_t row)
338 {
339     uint8_t pin = row_pins[row];
340     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
341     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
342 }
343
344 static void unselect_row(uint8_t row)
345 {
346     uint8_t pin = row_pins[row];
347     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
348     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
349 }
350
351 static void unselect_rows(void)
352 {
353     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
354         uint8_t pin = row_pins[x];
355         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
356         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
357     }
358 }
359
360 #else // ROW2COL
361
362 static void init_rows(void)
363 {
364     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
365         uint8_t pin = row_pins[x];
366         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
367         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
368     }
369 }
370
371 static matrix_col_t read_rows(void)
372 {
373     matrix_col_t result = 0;
374
375     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
376         uint8_t pin = row_pins[x];
377         result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (COL_SHIFTER << x);
378     }
379
380     return result;
381 }
382
383 static void select_col(uint8_t col)
384 {
385     uint8_t pin = col_pins[col];
386     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
387     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
388 }
389
390 static void unselect_col(uint8_t col)
391 {
392     uint8_t pin = col_pins[col];
393     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
394     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
395 }
396
397 static void unselect_cols(void)
398 {
399     for(uint8_t x = 0; x < MATRIX_COLS; x++) {
400         uint8_t pin = col_pins[x];
401         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
402         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
403     }
404 }
405
406 #endif