2 Copyright 2011 Jun Wako <wakojun@gmail.com>
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.
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.
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/>.
21 #include <util/delay.h>
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);
38 * 'Scan Code Set 2' is assigned into 256(32x8)cell matrix.
39 * Hmm, it is very sparse and not efficient :(
42 * Both 'Hanguel/English'(F1) and 'Hanja'(F2) collide with 'Delete'(E0 71) and 'Down'(E0 72).
43 * These two Korean keys need exceptional handling and are not supported for now. Sorry.
48 * :| XX | 00-7F for normal codes(without E0-prefix)
51 * :| E0 YY | 80-FF for E0-prefixed codes
52 * 1f| | (<YY>|0x80) is used as matrix position.
56 * 0x83: F7(0x83) This is a normal code but beyond 0x7F.
60 static uint8_t matrix[MATRIX_ROWS];
61 #define ROW(code) (code>>3)
62 #define COL(code) (code&0x07)
64 // matrix positions for exceptional keys
66 #define PRINT_SCREEN (0xFC)
69 static bool is_modified = false;
73 uint8_t matrix_rows(void)
79 uint8_t matrix_cols(void)
84 void matrix_init(void)
88 // initialize matrix state: all keys off
89 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
95 * PS/2 Scan Code Set 2: Exceptional Handling
97 * There are several keys to be handled exceptionally.
98 * The scan code for these keys are varied or prefix/postfix'd
99 * depending on modifier key state.
101 * Keyboard Scan Code Specification:
102 * http://www.microsoft.com/whdc/archive/scancode.mspx
103 * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
106 * 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left
107 * a) when Num Lock is off
108 * modifiers | make | break
109 * ----------+---------------------------+----------------------
110 * Ohter | <make> | <break>
111 * LShift | E0 F0 12 <make> | <break> E0 12
112 * RShift | E0 F0 59 <make> | <break> E0 59
113 * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
115 * b) when Num Lock is on
116 * modifiers | make | break
117 * ----------+---------------------------+----------------------
118 * Other | E0 12 <make> | <break> E0 F0 12
119 * Shift'd | <make> | <break>
121 * Handling: These prefix/postfix codes are ignored.
125 * modifiers | make | break
126 * ----------+---------------------------+----------------------
127 * Ohter | <make> | <break>
128 * LShift | E0 F0 12 <make> | <break> E0 12
129 * RShift | E0 F0 59 <make> | <break> E0 59
130 * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
132 * Handling: These prefix/postfix codes are ignored.
136 * modifiers | make | break
137 * ----------+--------------+-----------------------------------
138 * Other | E0 12 E0 7C | E0 F0 7C E0 F0 12
139 * Shift'd | E0 7C | E0 F0 7C
140 * Control'd | E0 7C | E0 F0 7C
143 * Handling: These prefix/postfix codes are ignored, and both scan codes
144 * 'E0 7C' and 84 are seen as PrintScreen.
147 * modifiers | make(no break code)
148 * ----------+--------------------------------------------------
149 * Other | E1 14 77 E1 F0 14 F0 77
150 * Control'd | E0 7E E0 F0 7E
152 * Handling: Both code sequences are treated as a whole.
153 * And we need a ad hoc 'pseudo break code' hack to get the key off
154 * because it has no break code.
157 uint8_t matrix_scan(void)
160 // scan code reading states
173 E1_14_77_E1_F0_14_F0,
183 // 'pseudo break code' hack
184 if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
189 while ((code = ps2_host_recv())) {
206 case 0x84: // Alt'd PrintScreen
207 matrix_make(PRINT_SCREEN);
210 default: // normal key make
214 debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
219 case E0: // E0-Prefixed
221 case 0x12: // to be ignored
222 case 0x59: // to be ignored
225 case 0x7E: // Control'd Pause
233 matrix_make(code|0x80);
235 debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
240 case F0: // Break code
246 case 0x84: // Alt'd PrintScreen
247 matrix_break(PRINT_SCREEN);
254 debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
259 case E0_F0: // Break code of E0-prefixed
261 case 0x12: // to be ignored
262 case 0x59: // to be ignored
267 matrix_break(code|0x80);
269 debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
274 // following are states of Pause
305 state = E1_14_77_E1_F0;
314 state = E1_14_77_E1_F0_14;
320 case E1_14_77_E1_F0_14:
323 state = E1_14_77_E1_F0_14_F0;
329 case E1_14_77_E1_F0_14_F0:
339 // Following are states of Control'd Pause
365 bool matrix_is_modified(void)
371 bool matrix_has_ghost(void)
373 #ifdef MATRIX_HAS_GHOST
374 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
375 if (matrix_has_ghost_in_row(i))
383 bool matrix_is_on(uint8_t row, uint8_t col)
385 return (matrix[row] & (1<<col));
389 uint8_t matrix_get_row(uint8_t row)
394 void matrix_print(void)
396 print("\nr/c 01234567\n");
397 for (uint8_t row = 0; row < matrix_rows(); row++) {
398 phex(row); print(": ");
399 pbin_reverse(matrix_get_row(row));
400 #ifdef MATRIX_HAS_GHOST
401 if (matrix_has_ghost_in_row(row)) {
409 uint8_t matrix_key_count(void)
412 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
413 count += bitpop(matrix[i]);
418 #ifdef MATRIX_HAS_GHOST
420 static bool matrix_has_ghost_in_row(uint8_t row)
422 // no ghost exists in case less than 2 keys on
423 if (((matrix[row] - 1) & matrix[row]) == 0)
426 // ghost exists in case same state as other row
427 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
428 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
437 static void matrix_make(uint8_t code)
439 if (!matrix_is_on(ROW(code), COL(code))) {
440 matrix[ROW(code)] |= 1<<COL(code);
446 static void matrix_break(uint8_t code)
448 if (matrix_is_on(ROW(code), COL(code))) {
449 matrix[ROW(code)] &= ~(1<<COL(code));