]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/matrix.c
reverts #343 for the most part (#474)
[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 /* Set 0 if debouncing isn't needed */
30 /*
31  * This constant define not debouncing time in msecs, but amount of matrix
32  * scan loops which should be made to get stable debounced results.
33  *
34  * On Ergodox matrix scan rate is relatively low, because of slow I2C.
35  * Now it's only 317 scans/second, or about 3.15 msec/scan.
36  * According to Cherry specs, debouncing time is 5 msec.
37  *
38  * And so, there is no sense to have DEBOUNCE higher than 2.
39  */
40
41 #ifndef DEBOUNCING_DELAY
42 #   define DEBOUNCING_DELAY 5
43 #endif
44 static uint8_t debouncing = DEBOUNCING_DELAY;
45
46 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
47 static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
48
49 /* matrix state(1:on, 0:off) */
50 static matrix_row_t matrix[MATRIX_ROWS];
51 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
52
53 #if DIODE_DIRECTION == ROW2COL
54     static matrix_row_t matrix_reversed[MATRIX_COLS];
55     static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
56 #endif
57
58 #if MATRIX_COLS > 16
59     #define SHIFTER 1UL
60 #else
61     #define SHIFTER 1
62 #endif
63
64 static matrix_row_t read_cols(void);
65 static void init_cols(void);
66 static void unselect_rows(void);
67 static void select_row(uint8_t row);
68
69 __attribute__ ((weak))
70 void matrix_init_quantum(void) {
71     matrix_init_kb();
72 }
73
74 __attribute__ ((weak))
75 void matrix_scan_quantum(void) {
76     matrix_scan_kb();
77 }
78
79 __attribute__ ((weak))
80 void matrix_init_kb(void) {
81     matrix_init_user();
82 }
83
84 __attribute__ ((weak))
85 void matrix_scan_kb(void) {
86     matrix_scan_user();
87 }
88
89 __attribute__ ((weak))
90 void matrix_init_user(void) {
91 }
92
93 __attribute__ ((weak))
94 void matrix_scan_user(void) {
95 }
96
97 inline
98 uint8_t matrix_rows(void) {
99     return MATRIX_ROWS;
100 }
101
102 inline
103 uint8_t matrix_cols(void) {
104     return MATRIX_COLS;
105 }
106
107 // void matrix_power_up(void) {
108 // #if DIODE_DIRECTION == COL2ROW
109 //     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
110 //         /* DDRxn */
111 //         _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
112 //         toggle_row(r);
113 //     }
114 //     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
115 //         /* PORTxn */
116 //         _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
117 //     }
118 // #else
119 //     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
120 //         /* DDRxn */
121 //         _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
122 //         toggle_col(c);
123 //     }
124 //     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
125 //         /* PORTxn */
126 //         _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
127 //     }
128 // #endif
129 // }
130
131 void matrix_init(void) {
132     // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
133     #ifdef __AVR_ATmega32U4__
134         MCUCR |= _BV(JTD);
135         MCUCR |= _BV(JTD);
136     #endif
137
138     // initialize row and col
139     unselect_rows();
140     init_cols();
141
142     // initialize matrix state: all keys off
143     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
144         matrix[i] = 0;
145         matrix_debouncing[i] = 0;
146     }
147
148     matrix_init_quantum();
149 }
150
151 uint8_t matrix_scan(void)
152 {
153
154 #if DIODE_DIRECTION == COL2ROW
155     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
156         select_row(i);
157         wait_us(30);  // without this wait read unstable value.
158         matrix_row_t cols = read_cols();
159         if (matrix_debouncing[i] != cols) {
160             matrix_debouncing[i] = cols;
161             if (debouncing) {
162                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
163             }
164             debouncing = DEBOUNCING_DELAY;
165         }
166         unselect_rows();
167     }
168
169     if (debouncing) {
170         if (--debouncing) {
171             wait_us(1);
172         } else {
173             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
174                 matrix[i] = matrix_debouncing[i];
175             }
176         }
177     }
178 #else
179     for (uint8_t i = 0; i < MATRIX_COLS; i++) {
180         select_row(i);
181         wait_us(30);  // without this wait read unstable value.
182         matrix_row_t rows = read_cols();
183         if (matrix_reversed_debouncing[i] != rows) {
184             matrix_reversed_debouncing[i] = rows;
185             if (debouncing) {
186                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
187             }
188             debouncing = DEBOUNCING_DELAY;
189         }
190         unselect_rows();
191     }
192
193     if (debouncing) {
194         if (--debouncing) {
195             wait_us(1);
196         } else {
197             for (uint8_t i = 0; i < MATRIX_COLS; i++) {
198                 matrix_reversed[i] = matrix_reversed_debouncing[i];
199             }
200         }
201     }
202     for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
203         matrix_row_t row = 0;
204         for (uint8_t x = 0; x < MATRIX_COLS; x++) {
205             row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
206         }
207         matrix[y] = row;
208     }
209 #endif
210
211     matrix_scan_quantum();
212
213     return 1;
214 }
215
216 bool matrix_is_modified(void)
217 {
218     if (debouncing) return false;
219     return true;
220 }
221
222 inline
223 bool matrix_is_on(uint8_t row, uint8_t col)
224 {
225     return (matrix[row] & ((matrix_row_t)1<col));
226 }
227
228 inline
229 matrix_row_t matrix_get_row(uint8_t row)
230 {
231     return matrix[row];
232 }
233
234 void matrix_print(void)
235 {
236     print("\nr/c 0123456789ABCDEF\n");
237     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
238         phex(row); print(": ");
239         pbin_reverse16(matrix_get_row(row));
240         print("\n");
241     }
242 }
243
244 uint8_t matrix_key_count(void)
245 {
246     uint8_t count = 0;
247     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
248         count += bitpop16(matrix[i]);
249     }
250     return count;
251 }
252
253 static void init_cols(void)
254 {
255 #if DIODE_DIRECTION == COL2ROW
256     for(int x = 0; x < MATRIX_COLS; x++) {
257         int pin = col_pins[x];
258 #else
259     for(int x = 0; x < MATRIX_ROWS; x++) {
260         int pin = row_pins[x];
261 #endif
262         _SFR_IO8((pin >> 4) + 1) &=  ~_BV(pin & 0xF);
263         _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
264     }
265 }
266
267 static matrix_row_t read_cols(void)
268 {
269     matrix_row_t result = 0;
270
271 #if DIODE_DIRECTION == COL2ROW
272     for(int x = 0; x < MATRIX_COLS; x++) {     
273         int pin = col_pins[x];
274 #else
275     for(int x = 0; x < MATRIX_ROWS; x++) {
276         int pin = row_pins[x];
277 #endif
278         result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
279     }
280     return result;
281 }
282
283 static void unselect_rows(void)
284 {
285 #if DIODE_DIRECTION == COL2ROW
286     for(int x = 0; x < MATRIX_ROWS; x++) { 
287         int pin = row_pins[x];
288 #else
289     for(int x = 0; x < MATRIX_COLS; x++) { 
290         int pin = col_pins[x];
291 #endif
292         _SFR_IO8((pin >> 4) + 1) &=  ~_BV(pin & 0xF);
293         _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
294     }
295 }
296
297 static void select_row(uint8_t row)
298 {
299
300 #if DIODE_DIRECTION == COL2ROW
301     int pin = row_pins[row];
302 #else
303     int pin = col_pins[row];
304 #endif
305     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF);
306     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
307 }