diff options
Diffstat (limited to 'keyboards/kmini/matrix.c')
-rwxr-xr-x | keyboards/kmini/matrix.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/keyboards/kmini/matrix.c b/keyboards/kmini/matrix.c new file mode 100755 index 000000000..f0733340c --- /dev/null +++ b/keyboards/kmini/matrix.c | |||
@@ -0,0 +1,303 @@ | |||
1 | /* Copyright 2018 Maarten Dekkers <maartenwut@gmail.com> | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include <stdint.h> | ||
17 | #include <stdbool.h> | ||
18 | #if defined(__AVR__) | ||
19 | #include <avr/io.h> | ||
20 | #endif | ||
21 | #include "wait.h" | ||
22 | #include "print.h" | ||
23 | #include "debug.h" | ||
24 | #include "util.h" | ||
25 | #include "matrix.h" | ||
26 | #include "timer.h" | ||
27 | |||
28 | |||
29 | /* Set 0 if debouncing isn't needed */ | ||
30 | #ifndef DEBOUNCING_DELAY | ||
31 | # define DEBOUNCING_DELAY 5 | ||
32 | #endif | ||
33 | |||
34 | #define COL_SHIFTER ((uint32_t)1) | ||
35 | |||
36 | static uint16_t debouncing_time; | ||
37 | static bool debouncing = false; | ||
38 | |||
39 | |||
40 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | ||
41 | |||
42 | /* matrix state(1:on, 0:off) */ | ||
43 | static matrix_row_t matrix[MATRIX_ROWS]; | ||
44 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | ||
45 | |||
46 | static void init_rows(void); | ||
47 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); | ||
48 | static void unselect_cols(void); | ||
49 | static void select_col(uint8_t col); | ||
50 | |||
51 | inline | ||
52 | uint8_t matrix_rows(void) { | ||
53 | return MATRIX_ROWS; | ||
54 | } | ||
55 | |||
56 | inline | ||
57 | uint8_t matrix_cols(void) { | ||
58 | return MATRIX_COLS; | ||
59 | } | ||
60 | |||
61 | void matrix_init(void) { | ||
62 | unselect_cols(); | ||
63 | init_rows(); | ||
64 | |||
65 | // initialize matrix state: all keys off | ||
66 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||
67 | matrix[i] = 0; | ||
68 | matrix_debouncing[i] = 0; | ||
69 | } | ||
70 | |||
71 | matrix_init_quantum(); | ||
72 | } | ||
73 | |||
74 | uint8_t matrix_scan(void) | ||
75 | { | ||
76 | // Set col, read rows | ||
77 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { | ||
78 | bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col); | ||
79 | if (matrix_changed) { | ||
80 | debouncing = true; | ||
81 | debouncing_time = timer_read(); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { | ||
86 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
87 | matrix[i] = matrix_debouncing[i]; | ||
88 | } | ||
89 | debouncing = false; | ||
90 | } | ||
91 | |||
92 | matrix_scan_quantum(); | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | inline | ||
97 | bool matrix_is_on(uint8_t row, uint8_t col) | ||
98 | { | ||
99 | return (matrix[row] & ((matrix_row_t)1<col)); | ||
100 | } | ||
101 | |||
102 | inline | ||
103 | matrix_row_t matrix_get_row(uint8_t row) | ||
104 | { | ||
105 | return matrix[row]; | ||
106 | } | ||
107 | |||
108 | void matrix_print(void) | ||
109 | { | ||
110 | print("\nr/c 0123456789ABCDEFGHIJKLMNOPQRSTUV \n"); | ||
111 | |||
112 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||
113 | phex(row); print(": "); | ||
114 | print_bin_reverse32(matrix_get_row(row)); | ||
115 | print("\n"); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | uint8_t matrix_key_count(void) | ||
120 | { | ||
121 | uint8_t count = 0; | ||
122 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
123 | count += bitpop32(matrix[i]); | ||
124 | } | ||
125 | return count; | ||
126 | } | ||
127 | |||
128 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) | ||
129 | { | ||
130 | bool matrix_changed = false; | ||
131 | |||
132 | // Select col and wait for col selecton to stabilize | ||
133 | select_col(current_col); | ||
134 | wait_us(30); | ||
135 | |||
136 | // For each row... | ||
137 | for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) | ||
138 | { | ||
139 | // Store last value of row prior to reading | ||
140 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
141 | |||
142 | // Check row pin state | ||
143 | // Use the otherwise unused row: 3, col: 0 for caps lock | ||
144 | if (row_index == 2 && current_col == 2) { | ||
145 | // Pin E2 uses active low | ||
146 | if ((_SFR_IO8(E2 >> 4) & _BV(E2 & 0xF)) == 0) | ||
147 | { | ||
148 | // Pin LO, set col bit | ||
149 | current_matrix[row_index] |= (COL_SHIFTER << current_col); | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | // Pin HI, clear col bit | ||
154 | current_matrix[row_index] &= ~(COL_SHIFTER << current_col); | ||
155 | } | ||
156 | } | ||
157 | else { | ||
158 | if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF))) | ||
159 | { | ||
160 | // Pin HI, set col bit | ||
161 | current_matrix[row_index] |= (COL_SHIFTER << current_col); | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | // Pin LO, clear col bit | ||
166 | current_matrix[row_index] &= ~(COL_SHIFTER << current_col); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // Determine if the matrix changed state | ||
171 | if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) | ||
172 | { | ||
173 | matrix_changed = true; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | // Unselect cols | ||
178 | unselect_cols(); | ||
179 | |||
180 | return matrix_changed; | ||
181 | } | ||
182 | |||
183 | /* Row pin configuration | ||
184 | * row: 0 1 2 3 4 | ||
185 | * pin: D0 D1 D2 D3 D5 | ||
186 | * | ||
187 | * Caps lock uses its own pin E2 | ||
188 | */ | ||
189 | static void init_rows(void) { | ||
190 | DDRD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // IN | ||
191 | PORTD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // LO | ||
192 | |||
193 | DDRE &= ~(1<<2); // IN | ||
194 | PORTE |= (1<<2); // HI | ||
195 | } | ||
196 | |||
197 | /* Columns 0 - 16 | ||
198 | * col 0: B5 | ||
199 | * col 1: B6 | ||
200 | * These columns use a 74HC237D 3 to 8 bit demultiplexer. | ||
201 | * A B C GL1 | ||
202 | * col / pin: PF0 PF1 PC7 PC6 | ||
203 | * 2: 0 0 0 1 | ||
204 | * 3: 1 0 0 1 | ||
205 | * 4: 0 1 0 1 | ||
206 | * 5: 1 1 0 1 | ||
207 | * 6: 0 0 1 1 | ||
208 | * 7: 1 0 1 1 | ||
209 | * 8: 0 1 1 1 | ||
210 | * 9: 1 1 1 1 | ||
211 | * col 10: E6 | ||
212 | * col 11: B0 | ||
213 | * col 12: B7 | ||
214 | * col 13: D4 | ||
215 | * col 14: D6 | ||
216 | * col 15: D7 | ||
217 | * col 16: B4 | ||
218 | */ | ||
219 | static void unselect_cols(void) { | ||
220 | DDRB |= (1<<5) | (1<<6) | (1<<0) | (1<<7) | (1<<4); // OUT | ||
221 | PORTB &= ~((1<<5) | (1<<6) | (1<<0) | (1<<7) | (1<<4)); // LO | ||
222 | |||
223 | DDRD |= (1<<4) | (1<<6) | (1<<7); // OUT | ||
224 | PORTD &= ~((1<<4) | (1<<6) | (1<<7)); // LO | ||
225 | |||
226 | DDRE |= (1<<6); // OUT | ||
227 | PORTE &= ~((1<<6)); // LO | ||
228 | |||
229 | DDRF |= (1<<0) | (1<<1); // OUT | ||
230 | PORTF &= ~((1<<0) | (1<<1)); // LO | ||
231 | |||
232 | DDRC |= (1<<7) | (1<<6); // OUT | ||
233 | PORTC &= ~((1<<7) | (1<<6)); // LO | ||
234 | } | ||
235 | |||
236 | static void select_col(uint8_t col) | ||
237 | { | ||
238 | switch (col) { | ||
239 | case 0: | ||
240 | PORTB |= (1<<5); // HI | ||
241 | break; | ||
242 | case 1: | ||
243 | PORTB |= (1<<6); // HI | ||
244 | break; | ||
245 | case 2: | ||
246 | PORTC |= (1<<6); // HI | ||
247 | break; | ||
248 | case 3: | ||
249 | PORTC |= (1<<6); // HI | ||
250 | PORTF |= (1<<0); // HI | ||
251 | break; | ||
252 | case 4: | ||
253 | PORTC |= (1<<6); // HI | ||
254 | PORTF |= (1<<1); // HI | ||
255 | break; | ||
256 | case 5: | ||
257 | PORTC |= (1<<6); // HI | ||
258 | PORTF |= (1<<0); // HI | ||
259 | PORTF |= (1<<1); // HI | ||
260 | break; | ||
261 | case 6: | ||
262 | PORTC |= (1<<6); // HI | ||
263 | PORTC |= (1<<7); // HI | ||
264 | break; | ||
265 | case 7: | ||
266 | PORTC |= (1<<6); // HI | ||
267 | PORTF |= (1<<0); // HI | ||
268 | PORTC |= (1<<7); // HI | ||
269 | break; | ||
270 | case 8: | ||
271 | PORTC |= (1<<6); // HI | ||
272 | PORTF |= (1<<1); // HI | ||
273 | PORTC |= (1<<7); // HI | ||
274 | break; | ||
275 | case 9: | ||
276 | PORTC |= (1<<6); // HI | ||
277 | PORTF |= (1<<0); // HI | ||
278 | PORTF |= (1<<1); // HI | ||
279 | PORTC |= (1<<7); // HI | ||
280 | break; | ||
281 | case 10: | ||
282 | PORTE |= (1<<6); // HI | ||
283 | break; | ||
284 | case 11: | ||
285 | PORTB |= (1<<0); // HI | ||
286 | break; | ||
287 | case 12: | ||
288 | PORTB |= (1<<7); // HI | ||
289 | break; | ||
290 | case 13: | ||
291 | PORTD |= (1<<4); // HI | ||
292 | break; | ||
293 | case 14: | ||
294 | PORTD |= (1<<6); // HI | ||
295 | break; | ||
296 | case 15: | ||
297 | PORTD |= (1<<7); // HI | ||
298 | break; | ||
299 | case 16: | ||
300 | PORTB |= (1<<4); // HI | ||
301 | break; | ||
302 | } | ||
303 | } | ||