Fix matrix_clear() for new matrix API
[tmk_keyboard.git] / converter / xt_usb / matrix.c
CommitLineData
3def1c30
EA
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along 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
29static void matrix_make(uint8_t code);
30static void matrix_break(uint8_t code);
3def1c30
EA
31#ifdef MATRIX_HAS_GHOST
32static bool matrix_has_ghost_in_row(uint8_t row);
33#endif
34
35static 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
43static bool is_modified = false;
44
45
46inline
47uint8_t matrix_rows(void)
48{
49 return MATRIX_ROWS;
50}
51
52inline
53uint8_t matrix_cols(void)
54{
55 return MATRIX_COLS;
56}
57
58void 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
69static 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
112uint8_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();
3def1c30
EA
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;
3def1c30 151 default: // normal key make
a9bce90c 152 if (code < 0x80 && code != 0x00) {
3def1c30
EA
153 xprintf("make: %X\r\n", code);
154 matrix_make(code);
a9bce90c 155 } else if (code > 0x80 && code < 0xFF && code != 0x00) {
3def1c30
EA
156 xprintf("break %X\r\n", code);
157 matrix_break(code - 0x80);
3def1c30
EA
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;
3def1c30 170 default:
a9bce90c 171 if (code < 0x80 && code != 0x00) {
3def1c30 172 matrix_make(move_codes(code));
a9bce90c 173 } else if (code > 0x80 && code < 0xFF && code != 0x00) {
3def1c30 174 matrix_break(move_codes(code - 0x80));
3def1c30
EA
175 }
176 state = INIT;
177 }
178 break;
179 case E0_2A:
a9bce90c
EA
180 if(code == 0xE0)
181 state = E0_2A_E0;
182 else
183 state = INIT;
3def1c30
EA
184 break;
185 case E0_2A_E0:
a9bce90c
EA
186 if(code == 0x37)
187 matrix_make(PRINT_SCREEN);
188 else
189 state = INIT;
3def1c30
EA
190 break;
191 case E0_B7:
a9bce90c
EA
192 if(code == 0xE0)
193 state = E0_B7;
194 else
195 state = INIT;
3def1c30
EA
196 break;
197 case E0_B7_E0:
a9bce90c
EA
198 if(code == 0xAA)
199 matrix_break(PRINT_SCREEN);
200 else
201 state = INIT;
3def1c30
EA
202 break;
203 case E1:
a9bce90c
EA
204 if (code == 0x1D)
205 state = E1_1D;
206 else
207 state = INIT;
3def1c30
EA
208 break;
209 case E1_1D:
a9bce90c
EA
210 if(code == 0x45)
211 state = E1_1D_45;
212 else
213 state = INIT;
3def1c30
EA
214 break;
215 case E1_1D_45:
a9bce90c
EA
216 if(code == 0xE1)
217 state = E1_1D_45_E1;
218 else
219 state = INIT;
3def1c30
EA
220 break;
221 case E1_1D_45_E1:
a9bce90c
EA
222 if(code == 0x9D)
223 state = E1_1D_45_E1_9D;
224 else
225 state = INIT;
3def1c30
EA
226 break;
227 case E1_1D_45_E1_9D:
a9bce90c
EA
228 if(code == 0xC5)
229 matrix_make(PAUSE);
230 else
231 state = INIT;
3def1c30
EA
232 break;
233 default:
234 state = INIT;
235 }
3def1c30
EA
236 return 1;
237}
238
239bool matrix_is_modified(void)
240{
241 return is_modified;
242}
243
244inline
245bool 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
256inline
257bool matrix_is_on(uint8_t row, uint8_t col)
258{
259 return (matrix[row] & (1<<col));
260}
261
262inline
263uint8_t matrix_get_row(uint8_t row)
264{
265 return matrix[row];
266}
267
268void 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
283uint8_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
293inline
294static 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
310inline
311static 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
319inline
320static 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
124bafe9 328void matrix_clear(void)
3def1c30
EA
329{
330 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
331}
Imprint / Impressum