]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - converter/xt_usb/matrix.c
xt_usb: Clear flag before enabling interrupt
[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
32 static uint8_t matrix[MATRIX_ROWS];
33 #define ROW(code)      (code>>3)
34 #define COL(code)      (code&0x07)
35
36 // matrix positions for exceptional keys
37 #define PRINT_SCREEN   (0x7C)
38 #define PAUSE          (0x7D)
39
40
41 void matrix_init(void)
42 {
43     debug_enable = true;
44     xt_host_init();
45
46     // initialize matrix state: all keys off
47     for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
48
49     return;
50 }
51
52 static uint8_t move_codes(uint8_t code) {
53     switch(code) {
54         case 0x10:
55             code += 0x5E;
56             break;
57         case 0x19:
58             code += 0x41;
59             break;
60         case 0x1C:
61         case 0x1D:
62             code += 0x38;
63             break;
64         case 0x20:
65         case 0x21:
66         case 0x22:
67         case 0x24:
68             code += 0x40;
69             break;
70         case 0x2E:
71         case 0x30:
72         case 0x32:
73             code += 0x44;
74             break;
75         case 0x35:
76         case 0x38:
77             code += 0x21;
78             break;
79         case 0x47:
80         case 0x48:
81         case 0x49:
82         case 0x4B:
83         case 0x4D:
84         case 0x4F:
85         case 0x50:
86         case 0x51:
87         case 0x52:
88         case 0x53:
89             code += 0x28;
90             break;
91     }
92     return code;
93 }
94
95 uint8_t matrix_scan(void)
96 {
97
98     // scan code reading states
99     static enum {
100         INIT,
101         E0,
102         E0_2A,
103         E0_2A_E0,
104         E0_B7,
105         E0_B7_E0,
106
107         // print screen
108         E1,
109         E1_1D,
110         E1_1D_45,
111         E1_1D_45_E1,
112         E1_1D_45_E1_9D,
113         // pause
114     } state = INIT;
115
116
117     // 'pseudo break code' hack
118     if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
119         matrix_break(PAUSE);
120     }
121
122     uint8_t code = xt_host_recv();
123     switch (state) {
124         case INIT:
125             switch (code) {
126                 case 0xE0:
127                     state = E0;
128                     break;
129                 case 0xE1:
130                     state = E1;
131                     break;
132                 default:    // normal key make
133                     if (code < 0x80 && code != 0x00) {
134                         xprintf("make: %X\r\n", code);
135                         matrix_make(code);
136                     } else if (code > 0x80 && code < 0xFF && code != 0x00) {
137                         xprintf("break %X\r\n", code);
138                         matrix_break(code - 0x80);
139                     }
140                     state = INIT;
141             }
142             break;
143         case E0:    // E0-Prefixed
144             switch (code) { //move these codes to unused places on the matrix
145                 case 0x2A:
146                     state = E0_2A;
147                     break;
148                 case 0xB7:
149                     state = E0_B7;
150                     break;
151                 default:
152                     if (code < 0x80 && code != 0x00) {
153                         matrix_make(move_codes(code));
154                     } else if (code > 0x80 && code < 0xFF && code != 0x00) {
155                         matrix_break(move_codes(code - 0x80));
156                     }
157                     state = INIT;
158             }
159             break;
160         case E0_2A:
161             if(code == 0xE0)
162                 state = E0_2A_E0;
163             else
164                 state = INIT;
165             break;
166         case E0_2A_E0:
167             if(code == 0x37)
168                 matrix_make(PRINT_SCREEN);
169             else
170                 state = INIT;
171             break;
172         case E0_B7:
173             if(code == 0xE0)
174                 state = E0_B7;
175             else
176                 state = INIT;
177             break;
178         case E0_B7_E0:
179           if(code == 0xAA)
180               matrix_break(PRINT_SCREEN);
181           else
182               state = INIT;
183           break;
184         case E1:
185             if (code == 0x1D)
186                 state = E1_1D;
187             else
188                 state = INIT;
189             break;
190         case E1_1D:
191             if(code == 0x45)
192                 state = E1_1D_45;
193             else
194                 state = INIT;
195             break;
196         case E1_1D_45:
197             if(code == 0xE1)
198                 state = E1_1D_45_E1;
199             else
200                 state = INIT;
201             break;
202         case E1_1D_45_E1:
203             if(code == 0x9D)
204                 state = E1_1D_45_E1_9D;
205             else
206                 state = INIT;
207             break;
208         case E1_1D_45_E1_9D:
209             if(code == 0xC5)
210                 matrix_make(PAUSE);
211             else
212                 state = INIT;
213             break;
214         default:
215             state = INIT;
216     }
217     return 1;
218 }
219
220 inline
221 uint8_t matrix_get_row(uint8_t row)
222 {
223     return matrix[row];
224 }
225
226 inline
227 static void matrix_make(uint8_t code)
228 {
229     if (!matrix_is_on(ROW(code), COL(code))) {
230         matrix[ROW(code)] |= 1<<COL(code);
231     }
232 }
233
234 inline
235 static void matrix_break(uint8_t code)
236 {
237     if (matrix_is_on(ROW(code), COL(code))) {
238         matrix[ROW(code)] &= ~(1<<COL(code));
239     }
240 }
241
242 void matrix_clear(void)
243 {
244     for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
245 }