]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/ergodox_ez/matrix.c
Eager Per Row Debouncing added (added to Ergodox) (#5498)
[qmk_firmware.git] / keyboards / ergodox_ez / matrix.c
1 /*
2
3 Note for ErgoDox EZ customizers: Here be dragons!
4 This is not a file you want to be messing with.
5 All of the interesting stuff for you is under keymaps/ :)
6 Love, Erez
7
8 Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /*
25  * scan matrix
26  */
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <avr/io.h>
30 #include "wait.h"
31 #include "action_layer.h"
32 #include "print.h"
33 #include "debug.h"
34 #include "util.h"
35 #include "matrix.h"
36 #include "debounce.h"
37 #include QMK_KEYBOARD_H
38 #ifdef DEBUG_MATRIX_SCAN_RATE
39 #  include "timer.h"
40 #endif
41
42 /*
43  * This constant define not debouncing time in msecs, assuming eager_pr.
44  *
45  * On Ergodox matrix scan rate is relatively low, because of slow I2C.
46  * Now it's only 317 scans/second, or about 3.15 msec/scan.
47  * According to Cherry specs, debouncing time is 5 msec.
48  *
49  * However, some switches seem to have higher debouncing requirements, or
50  * something else might be wrong. (Also, the scan speed has improved since
51  * that comment was written.)
52  */
53
54 #ifndef DEBOUNCE
55 #  define DEBOUNCE 5
56 #endif
57
58 /* matrix state(1:on, 0:off) */
59 static matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values
60 static matrix_row_t matrix[MATRIX_ROWS];      // debounced values
61
62 static matrix_row_t read_cols(uint8_t row);
63 static void         init_cols(void);
64 static void         unselect_rows(void);
65 static void         select_row(uint8_t row);
66
67 static uint8_t mcp23018_reset_loop;
68 // static uint16_t mcp23018_reset_loop;
69
70 #ifdef DEBUG_MATRIX_SCAN_RATE
71 uint32_t matrix_timer;
72 uint32_t matrix_scan_count;
73 #endif
74
75 __attribute__((weak)) void matrix_init_user(void) {}
76
77 __attribute__((weak)) void matrix_scan_user(void) {}
78
79 __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
80
81 __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
82
83 inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
84
85 inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
86
87 void matrix_init(void) {
88   // initialize row and col
89
90   mcp23018_status = init_mcp23018();
91
92   unselect_rows();
93   init_cols();
94
95   // initialize matrix state: all keys off
96   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
97     matrix[i]     = 0;
98     raw_matrix[i] = 0;    
99   }
100
101 #ifdef DEBUG_MATRIX_SCAN_RATE
102   matrix_timer      = timer_read32();
103   matrix_scan_count = 0;
104 #endif
105   debounce_init(MATRIX_ROWS);
106   matrix_init_quantum();
107 }
108
109 void matrix_power_up(void) {
110   mcp23018_status = init_mcp23018();
111
112   unselect_rows();
113   init_cols();
114
115   // initialize matrix state: all keys off
116   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
117     matrix[i] = 0;
118   }
119
120 #ifdef DEBUG_MATRIX_SCAN_RATE
121   matrix_timer      = timer_read32();
122   matrix_scan_count = 0;
123 #endif
124 }
125
126 uint8_t matrix_scan(void) {
127   if (mcp23018_status) {  // if there was an error
128     if (++mcp23018_reset_loop == 0) {
129       // if (++mcp23018_reset_loop >= 1300) {
130       // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
131       // this will be approx bit more frequent than once per second
132       print("trying to reset mcp23018\n");
133       mcp23018_status = init_mcp23018();
134       if (mcp23018_status) {
135         print("left side not responding\n");
136       } else {
137         print("left side attached\n");
138         ergodox_blink_all_leds();
139       }
140     }
141   }
142
143 #ifdef DEBUG_MATRIX_SCAN_RATE
144   matrix_scan_count++;
145
146   uint32_t timer_now = timer_read32();
147   if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
148     print("matrix scan frequency: ");
149     pdec(matrix_scan_count);
150     print("\n");
151
152     matrix_timer      = timer_now;
153     matrix_scan_count = 0;
154   }
155 #endif
156
157 #ifdef LEFT_LEDS
158   mcp23018_status = ergodox_left_leds_update();
159 #endif  // LEFT_LEDS
160   for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
161     // select rows from left and right hands
162     select_row(i);
163     select_row(i + MATRIX_ROWS_PER_SIDE);
164
165     // we don't need a 30us delay anymore, because selecting a
166     // left-hand row requires more than 30us for i2c.
167
168     // grab left + right cols.
169     raw_matrix[i] = read_cols(i);    
170     raw_matrix[i+MATRIX_ROWS_PER_SIDE] = read_cols(i+MATRIX_ROWS_PER_SIDE);
171     
172     unselect_rows();
173   }
174   
175   debounce(raw_matrix, matrix, MATRIX_ROWS, true);
176   matrix_scan_quantum();
177
178   return 1;
179 }
180
181 bool matrix_is_modified(void)  // deprecated and evidently not called.
182 {
183   return true;
184 }
185
186 inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
187
188 inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
189
190 void matrix_print(void) {
191   print("\nr/c 0123456789ABCDEF\n");
192   for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
193     phex(row);
194     print(": ");
195     pbin_reverse16(matrix_get_row(row));
196     print("\n");
197   }
198 }
199
200 uint8_t matrix_key_count(void) {
201   uint8_t count = 0;
202   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
203     count += bitpop16(matrix[i]);
204   }
205   return count;
206 }
207
208 /* Column pin configuration
209  *
210  * Teensy
211  * col: 0   1   2   3   4   5
212  * pin: F0  F1  F4  F5  F6  F7
213  *
214  * MCP23018
215  * col: 0   1   2   3   4   5
216  * pin: B5  B4  B3  B2  B1  B0
217  */
218 static void init_cols(void) {
219   // init on mcp23018
220   // not needed, already done as part of init_mcp23018()
221
222   // init on teensy
223   // Input with pull-up(DDR:0, PORT:1)
224   DDRF &= ~(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0);
225   PORTF |= (1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0);
226 }
227
228 static matrix_row_t read_cols(uint8_t row) {
229   if (row < 7) {
230     if (mcp23018_status) {  // if there was an error
231       return 0;
232     } else {
233       uint8_t data    = 0;
234       mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
235       if (mcp23018_status) goto out;
236       mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT);
237       if (mcp23018_status) goto out;
238       mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT);
239       if (mcp23018_status) goto out;
240       mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT);
241       if (mcp23018_status < 0) goto out;
242       data            = ~((uint8_t)mcp23018_status);
243       mcp23018_status = I2C_STATUS_SUCCESS;
244     out:
245       i2c_stop();
246       return data;
247     }
248   } else {
249     /* read from teensy
250      * bitmask is 0b11110011, but we want those all
251      * in the lower six bits.
252      * we'll return 1s for the top two, but that's harmless.
253      */
254
255     return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2));
256   }
257 }
258
259 /* Row pin configuration
260  *
261  * Teensy
262  * row: 7   8   9   10  11  12  13
263  * pin: B0  B1  B2  B3  D2  D3  C6
264  *
265  * MCP23018
266  * row: 0   1   2   3   4   5   6
267  * pin: A0  A1  A2  A3  A4  A5  A6
268  */
269 static void unselect_rows(void) {
270   // no need to unselect on mcp23018, because the select step sets all
271   // the other row bits high, and it's not changing to a different
272   // direction
273
274   // unselect on teensy
275   // Hi-Z(DDR:0, PORT:0) to unselect
276   DDRB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
277   PORTB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
278   DDRD &= ~(1 << 2 | 1 << 3);
279   PORTD &= ~(1 << 2 | 1 << 3);
280   DDRC &= ~(1 << 6);
281   PORTC &= ~(1 << 6);
282 }
283
284 static void select_row(uint8_t row) {
285   if (row < 7) {
286     // select on mcp23018
287     if (mcp23018_status) {  // if there was an error
288                             // do nothing
289     } else {
290       // set active row low  : 0
291       // set other rows hi-Z : 1
292       mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
293       if (mcp23018_status) goto out;
294       mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT);
295       if (mcp23018_status) goto out;
296       mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT);
297       if (mcp23018_status) goto out;
298     out:
299       i2c_stop();
300     }
301   } else {
302     // select on teensy
303     // Output low(DDR:1, PORT:0) to select
304     switch (row) {
305       case 7:
306         DDRB |= (1 << 0);
307         PORTB &= ~(1 << 0);
308         break;
309       case 8:
310         DDRB |= (1 << 1);
311         PORTB &= ~(1 << 1);
312         break;
313       case 9:
314         DDRB |= (1 << 2);
315         PORTB &= ~(1 << 2);
316         break;
317       case 10:
318         DDRB |= (1 << 3);
319         PORTB &= ~(1 << 3);
320         break;
321       case 11:
322         DDRD |= (1 << 2);
323         PORTD &= ~(1 << 2);
324         break;
325       case 12:
326         DDRD |= (1 << 3);
327         PORTD &= ~(1 << 3);
328         break;
329       case 13:
330         DDRC |= (1 << 6);
331         PORTC &= ~(1 << 6);
332         break;
333     }
334   }
335 }