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