]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - orphan/terminal_bluefruit/matrix.c
alps64: Change debouncing using timer count
[max/tmk_keyboard.git] / orphan / terminal_bluefruit / 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     debug_enable = true;
70     //debug_matrix = true;
71     //debug_keyboard = true;
72     //debug_mouse = false;
73
74     ps2_host_init();
75
76     // initialize matrix state: all keys off
77     for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
78
79     return;
80 }
81
82 uint8_t matrix_scan(void)
83 {
84
85     // scan code reading states
86     static enum {
87         RESET,
88         RESET_RESPONSE,
89         KBD_ID0,
90         KBD_ID1,
91         CONFIG,
92         READY,
93         F0,
94     } state = RESET;
95
96     is_modified = false;
97
98     uint8_t code;
99     if ((code = ps2_host_recv())) {
100         debug("r"); debug_hex(code); debug(" ");
101     }
102
103     switch (state) {
104         case RESET:
105             debug("wFF ");
106             if (ps2_host_send(0xFF) == 0xFA) {
107                 debug("[ack]\nRESET_RESPONSE: ");
108                 state = RESET_RESPONSE;
109             }
110             break;
111         case RESET_RESPONSE:
112             if (code == 0xAA) {
113                 debug("[ok]\nKBD_ID: ");
114                 state = KBD_ID0;
115             } else if (code) {
116                 debug("err\nRESET: ");
117                 state = RESET;
118             }
119             break;
120         // after reset receive keyboad ID(2 bytes)
121         case KBD_ID0:
122             if (code) {
123                 state = KBD_ID1;
124             }
125             break;
126         case KBD_ID1:
127             if (code) {
128                 debug("\nCONFIG: ");
129                 state = CONFIG;
130             }
131             break;
132         case CONFIG:
133             debug("wF8 ");
134             if (ps2_host_send(0xF8) == 0xFA) {
135                 debug("[ack]\nREADY\n");
136                 state = READY;
137             }
138             break;
139         case READY:
140             switch (code) {
141                 case 0x00:
142                     break;
143                 case 0xF0:
144                     state = F0;
145                     debug(" ");
146                     break;
147                 default:    // normal key make
148                     if (code < 0x88) {
149                         matrix_make(code);
150                     } else {
151                         debug("unexpected scan code at READY: "); debug_hex(code); debug("\n");
152                     }
153                     state = READY;
154                     debug("\n");
155             }
156             break;
157         case F0:    // Break code
158             switch (code) {
159                 case 0x00:
160                     break;
161                 default:
162                     if (code < 0x88) {
163                         matrix_break(code);
164                     } else {
165                         debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
166                     }
167                     state = READY;
168                     debug("\n");
169             }
170             break;
171     }
172     return 1;
173 }
174
175 bool matrix_is_modified(void)
176 {
177     return is_modified;
178 }
179
180 inline
181 bool matrix_has_ghost(void)
182 {
183 #ifdef MATRIX_HAS_GHOST
184     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
185         if (matrix_has_ghost_in_row(i))
186             return true;
187     }
188 #endif
189     return false;
190 }
191
192 inline
193 bool matrix_is_on(uint8_t row, uint8_t col)
194 {
195     return (matrix[row] & (1<<col));
196 }
197
198 inline
199 uint8_t matrix_get_row(uint8_t row)
200 {
201     return matrix[row];
202 }
203
204 void matrix_print(void)
205 {
206     print("\nr/c 01234567\n");
207     for (uint8_t row = 0; row < matrix_rows(); row++) {
208         phex(row); print(": ");
209         pbin_reverse(matrix_get_row(row));
210 #ifdef MATRIX_HAS_GHOST
211         if (matrix_has_ghost_in_row(row)) {
212             print(" <ghost");
213         }
214 #endif
215         print("\n");
216     }
217 }
218
219 uint8_t matrix_key_count(void)
220 {
221     uint8_t count = 0;
222     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
223         count += bitpop(matrix[i]);
224     }
225     return count;
226 }
227
228 #ifdef MATRIX_HAS_GHOST
229 inline
230 static bool matrix_has_ghost_in_row(uint8_t row)
231 {
232     // no ghost exists in case less than 2 keys on
233     if (((matrix[row] - 1) & matrix[row]) == 0)
234         return false;
235
236     // ghost exists in case same state as other row
237     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
238         if (i != row && (matrix[i] & matrix[row]) == matrix[row])
239             return true;
240     }
241     return false;
242 }
243 #endif
244
245
246 inline
247 static void matrix_make(uint8_t code)
248 {
249     if (!matrix_is_on(ROW(code), COL(code))) {
250         matrix[ROW(code)] |= 1<<COL(code);
251         is_modified = true;
252     }
253 }
254
255 inline
256 static void matrix_break(uint8_t code)
257 {
258     if (matrix_is_on(ROW(code), COL(code))) {
259         matrix[ROW(code)] &= ~(1<<COL(code));
260         is_modified = true;
261     }
262 }