]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/matrix.c
added ergodox
[qmk_firmware.git] / quantum / matrix.c
1 /*
2 Copyright 2012 Jun Wako 
3 Generated by planckkeyboard.com (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
19 /*
20  * scan matrix
21  */
22 #include <stdint.h>
23 #include <stdbool.h>
24 #include <avr/io.h>
25 #include <util/delay.h>
26 #include "print.h"
27 #include "debug.h"
28 #include "util.h"
29 #include "matrix.h"
30
31 #ifndef DEBOUNCE
32 #   define DEBOUNCE 10
33 #endif
34 static uint8_t debouncing = DEBOUNCE;
35
36 /* matrix state(1:on, 0:off) */
37 static matrix_row_t matrix[MATRIX_ROWS];
38 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
39
40 #if DIODE_DIRECTION == ROW2COL
41     static matrix_row_t matrix_reversed[MATRIX_COLS];
42     static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
43 #endif
44
45 static matrix_row_t read_cols(void);
46 static void init_cols(void);
47 static void unselect_rows(void);
48 static void select_row(uint8_t row);
49
50 __attribute__ ((weak))
51 void * matrix_init_kb(void) {
52
53 };
54
55 __attribute__ ((weak))
56 void * matrix_scan_kb(void) {
57
58 };
59
60 inline
61 uint8_t matrix_rows(void)
62 {
63     return MATRIX_ROWS;
64 }
65
66 inline
67 uint8_t matrix_cols(void)
68 {
69     return MATRIX_COLS;
70 }
71
72 void matrix_init(void)
73 {
74     // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
75     MCUCR |= (1<<JTD);
76     MCUCR |= (1<<JTD);
77
78
79     // initialize row and col
80     unselect_rows();
81     init_cols();
82
83     // initialize matrix state: all keys off
84     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
85         matrix[i] = 0;
86         matrix_debouncing[i] = 0;
87     }
88
89     if (matrix_init_kb) {
90         (*matrix_init_kb)();
91     }
92 }
93
94
95 uint8_t matrix_scan(void)
96 {
97
98 #if DIODE_DIRECTION == COL2ROW
99     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
100         select_row(i);
101         _delay_us(30);  // without this wait read unstable value.
102         matrix_row_t cols = read_cols();
103         if (matrix_debouncing[i] != cols) {
104             matrix_debouncing[i] = cols;
105             if (debouncing) {
106                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
107             }
108             debouncing = DEBOUNCE;
109         }
110         unselect_rows();
111     }
112
113     if (debouncing) {
114         if (--debouncing) {
115             _delay_ms(1);
116         } else {
117             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
118                 matrix[i] = matrix_debouncing[i];
119             }
120         }
121     }
122 #else
123     for (uint8_t i = 0; i < MATRIX_COLS; i++) {
124         select_row(i);
125         _delay_us(30);  // without this wait read unstable value.
126         matrix_row_t rows = read_cols();
127         if (matrix_reversed_debouncing[i] != rows) {
128             matrix_reversed_debouncing[i] = rows;
129             if (debouncing) {
130                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
131             }
132             debouncing = DEBOUNCE;
133         }
134         unselect_rows();
135     }
136
137     if (debouncing) {
138         if (--debouncing) {
139             _delay_ms(1);
140         } else {
141             for (uint8_t i = 0; i < MATRIX_COLS; i++) {
142                 matrix_reversed[i] = matrix_reversed_debouncing[i];
143             }
144         }
145     }
146     for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
147         matrix_row_t row = 0;
148         for (uint8_t x = 0; x < MATRIX_COLS; x++) {
149             row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
150         }
151         matrix[y] = row;
152     }
153 #endif
154
155     if (matrix_scan_kb) {
156         (*matrix_scan_kb)();
157     }
158
159     return 1;
160 }
161
162 bool matrix_is_modified(void)
163 {
164     if (debouncing) return false;
165     return true;
166 }
167
168 inline
169 bool matrix_is_on(uint8_t row, uint8_t col)
170 {
171     return (matrix[row] & ((matrix_row_t)1<col));
172 }
173
174 inline
175 matrix_row_t matrix_get_row(uint8_t row)
176 {
177     return matrix[row];
178 }
179
180 void matrix_print(void)
181 {
182     print("\nr/c 0123456789ABCDEF\n");
183     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
184         phex(row); print(": ");
185         pbin_reverse16(matrix_get_row(row));
186         print("\n");
187     }
188 }
189
190 uint8_t matrix_key_count(void)
191 {
192     uint8_t count = 0;
193     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
194         count += bitpop16(matrix[i]);
195     }
196     return count;
197 }
198
199 static void init_cols(void)
200 {
201     int B = 0, C = 0, D = 0, E = 0, F = 0;
202
203 #if DIODE_DIRECTION == COL2ROW
204     for(int x = 0; x < MATRIX_COLS; x++) {
205         int col = COLS[x];
206 #else
207     for(int x = 0; x < MATRIX_ROWS; x++) {
208         int col = ROWS[x];
209 #endif
210         if ((col & 0xF0) == 0x20) { 
211             B |= (1<<(col & 0x0F)); 
212         } else if ((col & 0xF0) == 0x30) { 
213             C |= (1<<(col & 0x0F)); 
214         } else if ((col & 0xF0) == 0x40) { 
215             D |= (1<<(col & 0x0F)); 
216         } else if ((col & 0xF0) == 0x50) { 
217             E |= (1<<(col & 0x0F)); 
218         } else if ((col & 0xF0) == 0x60) { 
219             F |= (1<<(col & 0x0F)); 
220         } 
221     }
222     DDRB &= ~(B); PORTB |= (B);
223     DDRC &= ~(C); PORTC |= (C); 
224     DDRD &= ~(D); PORTD |= (D);
225     DDRE &= ~(E); PORTE |= (E);
226     DDRF &= ~(F); PORTF |= (F);
227 }
228
229 static matrix_row_t read_cols(void)
230 {
231     matrix_row_t result = 0;
232
233 #if DIODE_DIRECTION == COL2ROW
234     for(int x = 0; x < MATRIX_COLS; x++) {     
235         int col = COLS[x];
236 #else
237     for(int x = 0; x < MATRIX_ROWS; x++) {
238         int col = ROWS[x];
239 #endif
240
241         if ((col & 0xF0) == 0x20) { 
242             result |= (PINB&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
243         } else if ((col & 0xF0) == 0x30) { 
244             result |= (PINC&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
245         } else if ((col & 0xF0) == 0x40) { 
246             result |= (PIND&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
247         } else if ((col & 0xF0) == 0x50) { 
248             result |= (PINE&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
249         } else if ((col & 0xF0) == 0x60) { 
250             result |= (PINF&(1<<(col & 0x0F)) ? 0 : (1<<x)); 
251         } 
252     }
253     return result;
254 }
255
256 static void unselect_rows(void)
257 {
258     int B = 0, C = 0, D = 0, E = 0, F = 0;
259
260 #if DIODE_DIRECTION == COL2ROW
261     for(int x = 0; x < MATRIX_ROWS; x++) { 
262         int row = ROWS[x];
263 #else
264     for(int x = 0; x < MATRIX_COLS; x++) { 
265         int row = COLS[x];
266 #endif
267         if ((row & 0xF0) == 0x20) { 
268             B |= (1<<(row & 0x0F)); 
269         } else if ((row & 0xF0) == 0x30) { 
270             C |= (1<<(row & 0x0F)); 
271         } else if ((row & 0xF0) == 0x40) { 
272             D |= (1<<(row & 0x0F)); 
273         } else if ((row & 0xF0) == 0x50) { 
274             E |= (1<<(row & 0x0F)); 
275         } else if ((row & 0xF0) == 0x60) { 
276             F |= (1<<(row & 0x0F)); 
277         } 
278     }
279     DDRB &= ~(B); PORTB |= (B);
280     DDRC &= ~(C); PORTC |= (C); 
281     DDRD &= ~(D); PORTD |= (D);
282     DDRE &= ~(E); PORTE |= (E);
283     DDRF &= ~(F); PORTF |= (F);
284 }
285
286 static void select_row(uint8_t row)
287 {
288
289 #if DIODE_DIRECTION == COL2ROW
290     int row_pin = ROWS[row];
291 #else
292     int row_pin = COLS[row];
293 #endif
294
295     if ((row_pin & 0xF0) == 0x20) { 
296         DDRB  |= (1<<(row_pin & 0x0F));
297         PORTB &= ~(1<<(row_pin & 0x0F));
298     } else if ((row_pin & 0xF0) == 0x30) { 
299         DDRC  |= (1<<(row_pin & 0x0F));
300         PORTC &= ~(1<<(row_pin & 0x0F));
301     } else if ((row_pin & 0xF0) == 0x40) { 
302         DDRD  |= (1<<(row_pin & 0x0F));
303         PORTD &= ~(1<<(row_pin & 0x0F));
304     } else if ((row_pin & 0xF0) == 0x50) { 
305         DDRE  |= (1<<(row_pin & 0x0F));
306         PORTE &= ~(1<<(row_pin & 0x0F));
307     } else if ((row_pin & 0xF0) == 0x60) { 
308         DDRF  |= (1<<(row_pin & 0x0F));
309         PORTF &= ~(1<<(row_pin & 0x0F));
310     }  
311 }