9e0c6247 |
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); |
9e0c6247 |
31 | |
32 | |
33 | /* |
34 | * Matrix Array usage: |
35 | * 'Scan Code Set 3' is assigned into 17x8 cell matrix. |
36 | * |
37 | * 8bit wide |
38 | * +---------+ |
39 | * 0| | |
40 | * :| | 0x00-0x87 |
41 | * ;| | |
42 | * 17| | |
43 | * +---------+ |
44 | */ |
45 | static uint8_t matrix[MATRIX_ROWS]; |
46 | #define ROW(code) (code>>3) |
47 | #define COL(code) (code&0x07) |
48 | |
9e0c6247 |
49 | |
50 | void matrix_init(void) |
51 | { |
9e0c6247 |
52 | debug_enable = true; |
53 | //debug_matrix = true; |
54 | //debug_keyboard = true; |
55 | //debug_mouse = false; |
56 | |
57 | ps2_host_init(); |
9e0c6247 |
58 | |
59 | // initialize matrix state: all keys off |
60 | for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; |
61 | |
62 | return; |
63 | } |
64 | |
65 | uint8_t matrix_scan(void) |
66 | { |
67 | |
68 | // scan code reading states |
69 | static enum { |
95001dd6 |
70 | RESET, |
71 | RESET_RESPONSE, |
72 | KBD_ID0, |
73 | KBD_ID1, |
74 | CONFIG, |
75 | READY, |
9e0c6247 |
76 | F0, |
95001dd6 |
77 | } state = RESET; |
9e0c6247 |
78 | |
9e0c6247 |
79 | uint8_t code; |
95001dd6 |
80 | if ((code = ps2_host_recv())) { |
81 | debug("r"); debug_hex(code); debug(" "); |
82 | } |
83 | |
84 | switch (state) { |
85 | case RESET: |
86 | debug("wFF "); |
87 | if (ps2_host_send(0xFF) == 0xFA) { |
88 | debug("[ack]\nRESET_RESPONSE: "); |
89 | state = RESET_RESPONSE; |
90 | } |
91 | break; |
92 | case RESET_RESPONSE: |
93 | if (code == 0xAA) { |
94 | debug("[ok]\nKBD_ID: "); |
95 | state = KBD_ID0; |
96 | } else if (code) { |
97 | debug("err\nRESET: "); |
98 | state = RESET; |
99 | } |
100 | break; |
101 | // after reset receive keyboad ID(2 bytes) |
102 | case KBD_ID0: |
103 | if (code) { |
104 | state = KBD_ID1; |
105 | } |
106 | break; |
107 | case KBD_ID1: |
108 | if (code) { |
109 | debug("\nCONFIG: "); |
110 | state = CONFIG; |
111 | } |
112 | break; |
113 | case CONFIG: |
114 | debug("wF8 "); |
115 | if (ps2_host_send(0xF8) == 0xFA) { |
116 | debug("[ack]\nREADY\n"); |
117 | state = READY; |
118 | } |
119 | break; |
120 | case READY: |
121 | switch (code) { |
122 | case 0x00: |
123 | break; |
124 | case 0xF0: |
125 | state = F0; |
126 | debug(" "); |
127 | break; |
128 | default: // normal key make |
129 | if (code < 0x88) { |
130 | matrix_make(code); |
131 | } else { |
132 | debug("unexpected scan code at READY: "); debug_hex(code); debug("\n"); |
133 | } |
134 | state = READY; |
135 | debug("\n"); |
136 | } |
137 | break; |
138 | case F0: // Break code |
139 | switch (code) { |
140 | case 0x00: |
141 | break; |
142 | default: |
9e0c6247 |
143 | if (code < 0x88) { |
144 | matrix_break(code); |
145 | } else { |
146 | debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); |
147 | } |
95001dd6 |
148 | state = READY; |
9e0c6247 |
149 | debug("\n"); |
95001dd6 |
150 | } |
151 | break; |
9e0c6247 |
152 | } |
153 | return 1; |
154 | } |
155 | |
9e0c6247 |
156 | inline |
157 | uint8_t matrix_get_row(uint8_t row) |
158 | { |
159 | return matrix[row]; |
160 | } |
161 | |
9e0c6247 |
162 | inline |
163 | static void matrix_make(uint8_t code) |
164 | { |
165 | if (!matrix_is_on(ROW(code), COL(code))) { |
166 | matrix[ROW(code)] |= 1<<COL(code); |
9e0c6247 |
167 | } |
168 | } |
169 | |
170 | inline |
171 | static void matrix_break(uint8_t code) |
172 | { |
173 | if (matrix_is_on(ROW(code), COL(code))) { |
174 | matrix[ROW(code)] &= ~(1<<COL(code)); |
9e0c6247 |
175 | } |
176 | } |