Fix matrix_clear() for new matrix API
[tmk_keyboard.git] / converter / xt_usb / matrix.c
1 /*
2 Copyright 2011 Jun Wako <wakojun@gmail.com>
3 Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
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 #include <stdint.h>
20 #include <stdbool.h>
21 #include "action.h"
22 #include "print.h"
23 #include "util.h"
24 #include "debug.h"
25 #include "xt.h"
26 #include "matrix.h"
27
28
29 static void matrix_make(uint8_t code);
30 static void matrix_break(uint8_t code);
31 #ifdef MATRIX_HAS_GHOST
32 static bool matrix_has_ghost_in_row(uint8_t row);
33 #endif
34
35 static uint8_t matrix[MATRIX_ROWS];
36 #define ROW(code) (code>>3)
37 #define COL(code) (code&0x07)
38
39 // matrix positions for exceptional keys
40 #define PRINT_SCREEN (0x7C)
41 #define PAUSE (0x7D)
42
43 static bool is_modified = false;
44
45
46 inline
47 uint8_t matrix_rows(void)
48 {
49 return MATRIX_ROWS;
50 }
51
52 inline
53 uint8_t matrix_cols(void)
54 {
55 return MATRIX_COLS;
56 }
57
58 void matrix_init(void)
59 {
60 debug_enable = true;
61 xt_host_init();
62
63 // initialize matrix state: all keys off
64 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
65
66 return;
67 }
68
69 static uint8_t move_codes(uint8_t code) {
70 switch(code) {
71 case 0x10:
72 code += 0x5E;
73 break;
74 case 0x19:
75 code += 0x41;
76 break;
77 case 0x1C:
78 case 0x1D:
79 code += 0x38;
80 break;
81 case 0x20:
82 case 0x21:
83 case 0x22:
84 case 0x24:
85 code += 0x40;
86 break;
87 case 0x2E:
88 case 0x30:
89 case 0x32:
90 code += 0x44;
91 break;
92 case 0x35:
93 case 0x38:
94 code += 0x21;
95 break;
96 case 0x47:
97 case 0x48:
98 case 0x49:
99 case 0x4B:
100 case 0x4D:
101 case 0x4F:
102 case 0x50:
103 case 0x51:
104 case 0x52:
105 case 0x53:
106 code += 0x28;
107 break;
108 }
109 return code;
110 }
111
112 uint8_t matrix_scan(void)
113 {
114
115 // scan code reading states
116 static enum {
117 INIT,
118 E0,
119 E0_2A,
120 E0_2A_E0,
121 E0_B7,
122 E0_B7_E0,
123
124 // print screen
125 E1,
126 E1_1D,
127 E1_1D_45,
128 E1_1D_45_E1,
129 E1_1D_45_E1_9D,
130 // pause
131 } state = INIT;
132
133
134 is_modified = false;
135
136 // 'pseudo break code' hack
137 if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
138 matrix_break(PAUSE);
139 }
140
141 uint8_t code = xt_host_recv();
142 switch (state) {
143 case INIT:
144 switch (code) {
145 case 0xE0:
146 state = E0;
147 break;
148 case 0xE1:
149 state = E1;
150 break;
151 default: // normal key make
152 if (code < 0x80 && code != 0x00) {
153 xprintf("make: %X\r\n", code);
154 matrix_make(code);
155 } else if (code > 0x80 && code < 0xFF && code != 0x00) {
156 xprintf("break %X\r\n", code);
157 matrix_break(code - 0x80);
158 }
159 state = INIT;
160 }
161 break;
162 case E0: // E0-Prefixed
163 switch (code) { //move these codes to unused places on the matrix
164 case 0x2A:
165 state = E0_2A;
166 break;
167 case 0xB7:
168 state = E0_B7;
169 break;
170 default:
171 if (code < 0x80 && code != 0x00) {
172 matrix_make(move_codes(code));
173 } else if (code > 0x80 && code < 0xFF && code != 0x00) {
174 matrix_break(move_codes(code - 0x80));
175 }
176 state = INIT;
177 }
178 break;
179 case E0_2A:
180 if(code == 0xE0)
181 state = E0_2A_E0;
182 else
183 state = INIT;
184 break;
185 case E0_2A_E0:
186 if(code == 0x37)
187 matrix_make(PRINT_SCREEN);
188 else
189 state = INIT;
190 break;
191 case E0_B7:
192 if(code == 0xE0)
193 state = E0_B7;
194 else
195 state = INIT;
196 break;
197 case E0_B7_E0:
198 if(code == 0xAA)
199 matrix_break(PRINT_SCREEN);
200 else
201 state = INIT;
202 break;
203 case E1:
204 if (code == 0x1D)
205 state = E1_1D;
206 else
207 state = INIT;
208 break;
209 case E1_1D:
210 if(code == 0x45)
211 state = E1_1D_45;
212 else
213 state = INIT;
214 break;
215 case E1_1D_45:
216 if(code == 0xE1)
217 state = E1_1D_45_E1;
218 else
219 state = INIT;
220 break;
221 case E1_1D_45_E1:
222 if(code == 0x9D)
223 state = E1_1D_45_E1_9D;
224 else
225 state = INIT;
226 break;
227 case E1_1D_45_E1_9D:
228 if(code == 0xC5)
229 matrix_make(PAUSE);
230 else
231 state = INIT;
232 break;
233 default:
234 state = INIT;
235 }
236 return 1;
237 }
238
239 bool matrix_is_modified(void)
240 {
241 return is_modified;
242 }
243
244 inline
245 bool matrix_has_ghost(void)
246 {
247 #ifdef MATRIX_HAS_GHOST
248 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
249 if (matrix_has_ghost_in_row(i))
250 return true;
251 }
252 #endif
253 return false;
254 }
255
256 inline
257 bool matrix_is_on(uint8_t row, uint8_t col)
258 {
259 return (matrix[row] & (1<<col));
260 }
261
262 inline
263 uint8_t matrix_get_row(uint8_t row)
264 {
265 return matrix[row];
266 }
267
268 void matrix_print(void)
269 {
270 print("\nr/c 01234567\n");
271 for (uint8_t row = 0; row < matrix_rows(); row++) {
272 phex(row); print(": ");
273 pbin_reverse(matrix_get_row(row));
274 #ifdef MATRIX_HAS_GHOST
275 if (matrix_has_ghost_in_row(row)) {
276 print(" <ghost");
277 }
278 #endif
279 print("\n");
280 }
281 }
282
283 uint8_t matrix_key_count(void)
284 {
285 uint8_t count = 0;
286 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
287 count += bitpop(matrix[i]);
288 }
289 return count;
290 }
291
292 #ifdef MATRIX_HAS_GHOST
293 inline
294 static bool matrix_has_ghost_in_row(uint8_t row)
295 {
296 // no ghost exists in case less than 2 keys on
297 if (((matrix[row] - 1) & matrix[row]) == 0)
298 return false;
299
300 // ghost exists in case same state as other row
301 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
302 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
303 return true;
304 }
305 return false;
306 }
307 #endif
308
309
310 inline
311 static void matrix_make(uint8_t code)
312 {
313 if (!matrix_is_on(ROW(code), COL(code))) {
314 matrix[ROW(code)] |= 1<<COL(code);
315 is_modified = true;
316 }
317 }
318
319 inline
320 static void matrix_break(uint8_t code)
321 {
322 if (matrix_is_on(ROW(code), COL(code))) {
323 matrix[ROW(code)] &= ~(1<<COL(code));
324 is_modified = true;
325 }
326 }
327
328 void matrix_clear(void)
329 {
330 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
331 }
Imprint / Impressum