]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/ergodox_ez/matrix.c
22837d312a2f3908e1648678298d7743c9fee61b
[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 QMK_KEYBOARD_H
37 #ifdef DEBUG_MATRIX_SCAN_RATE
38 #include  "timer.h"
39 #endif
40
41 /*
42  * This constant define not debouncing time in msecs, but amount of matrix
43  * scan loops which should be made to get stable debounced results.
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 matrix[MATRIX_ROWS];
60 /*
61  * matrix state(1:on, 0:off)
62  * contains the raw values without debounce filtering of the last read cycle.
63  */
64 static matrix_row_t raw_matrix[MATRIX_ROWS];
65
66 // Debouncing: store for each key the number of scans until it's eligible to
67 // change.  When scanning the matrix, ignore any changes in keys that have
68 // already changed in the last DEBOUNCE scans.
69 static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
70
71 static matrix_row_t read_cols(uint8_t row);
72 static void init_cols(void);
73 static void unselect_rows(void);
74 static void select_row(uint8_t row);
75
76 static uint8_t mcp23018_reset_loop;
77 // static uint16_t mcp23018_reset_loop;
78
79 #ifdef DEBUG_MATRIX_SCAN_RATE
80 uint32_t matrix_timer;
81 uint32_t matrix_scan_count;
82 #endif
83
84
85 __attribute__ ((weak))
86 void matrix_init_user(void) {}
87
88 __attribute__ ((weak))
89 void matrix_scan_user(void) {}
90
91 __attribute__ ((weak))
92 void matrix_init_kb(void) {
93   matrix_init_user();
94 }
95
96 __attribute__ ((weak))
97 void matrix_scan_kb(void) {
98   matrix_scan_user();
99 }
100
101 inline
102 uint8_t matrix_rows(void)
103 {
104     return MATRIX_ROWS;
105 }
106
107 inline
108 uint8_t matrix_cols(void)
109 {
110     return MATRIX_COLS;
111 }
112
113 void matrix_init(void)
114 {
115     // initialize row and col
116
117     mcp23018_status = init_mcp23018();
118
119
120     unselect_rows();
121     init_cols();
122
123     // initialize matrix state: all keys off
124     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
125         matrix[i] = 0;
126         raw_matrix[i] = 0;
127         for (uint8_t j=0; j < MATRIX_COLS; ++j) {
128             debounce_matrix[i * MATRIX_COLS + j] = 0;
129         }
130     }
131
132 #ifdef DEBUG_MATRIX_SCAN_RATE
133     matrix_timer = timer_read32();
134     matrix_scan_count = 0;
135 #endif
136
137     matrix_init_quantum();
138
139 }
140
141 void matrix_power_up(void) {
142     mcp23018_status = init_mcp23018();
143
144     unselect_rows();
145     init_cols();
146
147     // initialize matrix state: all keys off
148     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
149         matrix[i] = 0;
150     }
151
152 #ifdef DEBUG_MATRIX_SCAN_RATE
153     matrix_timer = timer_read32();
154     matrix_scan_count = 0;
155 #endif
156 }
157
158 // Returns a matrix_row_t whose bits are set if the corresponding key should be
159 // eligible to change in this scan.
160 matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) {
161   matrix_row_t result = 0;
162   matrix_row_t change = rawcols ^ raw_matrix[row];
163   raw_matrix[row] = rawcols;
164   for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
165     if (debounce_matrix[row * MATRIX_COLS + i]) {
166       --debounce_matrix[row * MATRIX_COLS + i];
167     } else {
168       result |= (1 << i);
169     }
170     if (change & (1 << i)) {
171       debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
172     }
173   }
174   return result;
175 }
176
177 matrix_row_t debounce_read_cols(uint8_t row) {
178   // Read the row without debouncing filtering and store it for later usage.
179   matrix_row_t cols = read_cols(row);
180   // Get the Debounce mask.
181   matrix_row_t mask = debounce_mask(cols, row);
182   // debounce the row and return the result.
183   return (cols & mask) | (matrix[row] & ~mask);;
184 }
185
186 uint8_t matrix_scan(void)
187 {
188     if (mcp23018_status) { // if there was an error
189         if (++mcp23018_reset_loop == 0) {
190         // if (++mcp23018_reset_loop >= 1300) {
191             // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
192             // this will be approx bit more frequent than once per second
193             print("trying to reset mcp23018\n");
194             mcp23018_status = init_mcp23018();
195             if (mcp23018_status) {
196                 print("left side not responding\n");
197             } else {
198                 print("left side attached\n");
199                 ergodox_blink_all_leds();
200             }
201         }
202     }
203
204 #ifdef DEBUG_MATRIX_SCAN_RATE
205     matrix_scan_count++;
206
207     uint32_t timer_now = timer_read32();
208     if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
209         print("matrix scan frequency: ");
210         pdec(matrix_scan_count);
211         print("\n");
212
213         matrix_timer = timer_now;
214         matrix_scan_count = 0;
215     }
216 #endif
217
218 #ifdef LEFT_LEDS
219     mcp23018_status = ergodox_left_leds_update();
220 #endif // LEFT_LEDS
221     for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
222         select_row(i);
223         // and select on left hand
224         select_row(i + MATRIX_ROWS_PER_SIDE);
225         // we don't need a 30us delay anymore, because selecting a
226         // left-hand row requires more than 30us for i2c.
227
228         // grab cols from left hand
229         matrix[i] = debounce_read_cols(i);
230         // grab cols from right hand
231         matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE);
232
233         unselect_rows();
234     }
235
236     matrix_scan_quantum();
237
238     return 1;
239 }
240
241 bool matrix_is_modified(void) // deprecated and evidently not called.
242 {
243     return true;
244 }
245
246 inline
247 bool matrix_is_on(uint8_t row, uint8_t col)
248 {
249     return (matrix[row] & ((matrix_row_t)1<<col));
250 }
251
252 inline
253 matrix_row_t matrix_get_row(uint8_t row)
254 {
255     return matrix[row];
256 }
257
258 void matrix_print(void)
259 {
260     print("\nr/c 0123456789ABCDEF\n");
261     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
262         phex(row); print(": ");
263         pbin_reverse16(matrix_get_row(row));
264         print("\n");
265     }
266 }
267
268 uint8_t matrix_key_count(void)
269 {
270     uint8_t count = 0;
271     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
272         count += bitpop16(matrix[i]);
273     }
274     return count;
275 }
276
277 /* Column pin configuration
278  *
279  * Teensy
280  * col: 0   1   2   3   4   5
281  * pin: F0  F1  F4  F5  F6  F7
282  *
283  * MCP23018
284  * col: 0   1   2   3   4   5
285  * pin: B5  B4  B3  B2  B1  B0
286  */
287 static void  init_cols(void)
288 {
289     // init on mcp23018
290     // not needed, already done as part of init_mcp23018()
291
292     // init on teensy
293     // Input with pull-up(DDR:0, PORT:1)
294     DDRF  &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
295     PORTF |=  (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
296 }
297
298 static matrix_row_t read_cols(uint8_t row)
299 {
300     if (row < 7) {
301         if (mcp23018_status) { // if there was an error
302             return 0;
303         } else {
304             uint8_t data = 0;
305             mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);    if (mcp23018_status) goto out;
306             mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT);             if (mcp23018_status) goto out;
307             mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT);     if (mcp23018_status) goto out;
308             mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT);                if (mcp23018_status < 0) goto out;
309             data = ~((uint8_t)mcp23018_status);
310             mcp23018_status = I2C_STATUS_SUCCESS;
311         out:
312             i2c_stop(ERGODOX_EZ_I2C_TIMEOUT);
313             return data;
314         }
315     } else {
316         /* read from teensy
317          * bitmask is 0b11110011, but we want those all
318          * in the lower six bits.
319          * we'll return 1s for the top two, but that's harmless.
320          */
321
322         return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2));
323     }
324 }
325
326 /* Row pin configuration
327  *
328  * Teensy
329  * row: 7   8   9   10  11  12  13
330  * pin: B0  B1  B2  B3  D2  D3  C6
331  *
332  * MCP23018
333  * row: 0   1   2   3   4   5   6
334  * pin: A0  A1  A2  A3  A4  A5  A6
335  */
336 static void unselect_rows(void)
337 {
338     // no need to unselect on mcp23018, because the select step sets all
339     // the other row bits high, and it's not changing to a different
340     // direction
341
342     // unselect on teensy
343     // Hi-Z(DDR:0, PORT:0) to unselect
344     DDRB  &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
345     PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
346     DDRD  &= ~(1<<2 | 1<<3);
347     PORTD &= ~(1<<2 | 1<<3);
348     DDRC  &= ~(1<<6);
349     PORTC &= ~(1<<6);
350 }
351
352 static void select_row(uint8_t row)
353 {
354     if (row < 7) {
355         // select on mcp23018
356         if (mcp23018_status) { // if there was an error
357             // do nothing
358         } else {
359             // set active row low  : 0
360             // set other rows hi-Z : 1
361             mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);        if (mcp23018_status) goto out;
362             mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT);                 if (mcp23018_status) goto out;
363             mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT);      if (mcp23018_status) goto out;
364         out:
365             i2c_stop(ERGODOX_EZ_I2C_TIMEOUT);
366         }
367     } else {
368         // select on teensy
369         // Output low(DDR:1, PORT:0) to select
370         switch (row) {
371             case 7:
372                 DDRB  |= (1<<0);
373                 PORTB &= ~(1<<0);
374                 break;
375             case 8:
376                 DDRB  |= (1<<1);
377                 PORTB &= ~(1<<1);
378                 break;
379             case 9:
380                 DDRB  |= (1<<2);
381                 PORTB &= ~(1<<2);
382                 break;
383             case 10:
384                 DDRB  |= (1<<3);
385                 PORTB &= ~(1<<3);
386                 break;
387             case 11:
388                 DDRD  |= (1<<2);
389                 PORTD &= ~(1<<2);
390                 break;
391             case 12:
392                 DDRD  |= (1<<3);
393                 PORTD &= ~(1<<3);
394                 break;
395             case 13:
396                 DDRC  |= (1<<6);
397                 PORTC &= ~(1<<6);
398                 break;
399         }
400     }
401 }