]> git.gir.st - tmk_keyboard.git/blob - converter/terminal_usb/matrix.c
Merge branch 'newdir'
[tmk_keyboard.git] / converter / terminal_usb / matrix.c
1 /*
2 Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include <avr/io.h>
21 #include <util/delay.h>
22 #include "print.h"
23 #include "util.h"
24 #include "debug.h"
25 #include "ps2.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
36 /*
37 * Matrix Array usage:
38 * 'Scan Code Set 3' is assigned into 17x8 cell matrix.
39 *
40 * 8bit wide
41 * +---------+
42 * 0| |
43 * :| | 0x00-0x87
44 * ;| |
45 * 17| |
46 * +---------+
47 */
48 static uint8_t matrix[MATRIX_ROWS];
49 #define ROW(code) (code>>3)
50 #define COL(code) (code&0x07)
51
52 static bool is_modified = false;
53
54
55 inline
56 uint8_t matrix_rows(void)
57 {
58 return MATRIX_ROWS;
59 }
60
61 inline
62 uint8_t matrix_cols(void)
63 {
64 return MATRIX_COLS;
65 }
66
67 void matrix_init(void)
68 {
69 print_enable = true;
70 debug_enable = true;
71 //debug_matrix = true;
72 //debug_keyboard = true;
73 //debug_mouse = false;
74
75 ps2_host_init();
76 // Make and Break code without Typematic
77 while (ps2_host_send(0xF8) != 0xFA) {
78 debug("send F8: failed\n");
79 _delay_ms(500);
80 }
81 debug("send F8: OK\n");
82
83
84 // initialize matrix state: all keys off
85 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
86
87 return;
88 }
89
90 uint8_t matrix_scan(void)
91 {
92
93 // scan code reading states
94 static enum {
95 INIT,
96 F0,
97 } state = INIT;
98
99
100 is_modified = false;
101
102 uint8_t code;
103 while ((code = ps2_host_recv())) {
104 debug_hex(code);
105 switch (state) {
106 case INIT:
107 switch (code) {
108 case 0xF0:
109 state = F0;
110 debug(" ");
111 break;
112 default: // normal key make
113 if (code < 0x88) {
114 matrix_make(code);
115 } else {
116 debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
117 }
118 state = INIT;
119 debug("\n");
120 }
121 break;
122 case F0: // Break code
123 switch (code) {
124 default:
125 if (code < 0x88) {
126 matrix_break(code);
127 } else {
128 debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
129 }
130 state = INIT;
131 debug("\n");
132 }
133 break;
134 }
135 }
136 return 1;
137 }
138
139 bool matrix_is_modified(void)
140 {
141 return is_modified;
142 }
143
144 inline
145 bool matrix_has_ghost(void)
146 {
147 #ifdef MATRIX_HAS_GHOST
148 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
149 if (matrix_has_ghost_in_row(i))
150 return true;
151 }
152 #endif
153 return false;
154 }
155
156 inline
157 bool matrix_is_on(uint8_t row, uint8_t col)
158 {
159 return (matrix[row] & (1<<col));
160 }
161
162 inline
163 uint8_t matrix_get_row(uint8_t row)
164 {
165 return matrix[row];
166 }
167
168 void matrix_print(void)
169 {
170 print("\nr/c 01234567\n");
171 for (uint8_t row = 0; row < matrix_rows(); row++) {
172 phex(row); print(": ");
173 pbin_reverse(matrix_get_row(row));
174 #ifdef MATRIX_HAS_GHOST
175 if (matrix_has_ghost_in_row(row)) {
176 print(" <ghost");
177 }
178 #endif
179 print("\n");
180 }
181 }
182
183 uint8_t matrix_key_count(void)
184 {
185 uint8_t count = 0;
186 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
187 count += bitpop(matrix[i]);
188 }
189 return count;
190 }
191
192 #ifdef MATRIX_HAS_GHOST
193 inline
194 static bool matrix_has_ghost_in_row(uint8_t row)
195 {
196 // no ghost exists in case less than 2 keys on
197 if (((matrix[row] - 1) & matrix[row]) == 0)
198 return false;
199
200 // ghost exists in case same state as other row
201 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
202 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
203 return true;
204 }
205 return false;
206 }
207 #endif
208
209
210 inline
211 static void matrix_make(uint8_t code)
212 {
213 if (!matrix_is_on(ROW(code), COL(code))) {
214 matrix[ROW(code)] |= 1<<COL(code);
215 is_modified = true;
216 }
217 }
218
219 inline
220 static void matrix_break(uint8_t code)
221 {
222 if (matrix_is_on(ROW(code), COL(code))) {
223 matrix[ROW(code)] &= ~(1<<COL(code));
224 is_modified = true;
225 }
226 }
Imprint / Impressum