7 #include <util/delay.h>
12 #include "usb_keyboard.h"
13 #include "matrix_skel.h"
16 #if (MATRIX_COLS > 16)
17 # error "MATRIX_COLS must not exceed 16"
19 #if (MATRIX_ROWS > 255)
20 # error "MATRIX_ROWS must not exceed 255"
26 * "PS/2 Scan Codes Set 2" is assigned to 256(32x8)cells matrix.
27 * Hmm, It is very sparse and not efficient :(
32 * :| XX | 00-7F for normal codes
35 * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code)
39 * 0x83: F8(normal code placed beyond 0x7F)
43 #define _PRINT_SCREEN (0xFE)
44 #define _PAUSE_BREAK (0xFF)
45 #define _ROW(code) (code>>3)
46 #define _COL(code) (code&0x07)
48 static bool _matrix_is_modified = false;
50 // matrix state buffer(1:on, 0:off)
51 #if (MATRIX_COLS <= 8)
52 static uint8_t *matrix;
53 static uint8_t _matrix0[MATRIX_ROWS];
55 static uint16_t *matrix;
56 static uint16_t _matrix0[MATRIX_ROWS];
59 #ifdef MATRIX_HAS_GHOST
60 static bool matrix_has_ghost_in_row(uint8_t row);
62 static void _matrix_make(uint8_t code);
63 static void _matrix_break(uint8_t code);
64 static void _ps2_reset(void);
65 static void _ps2_set_leds(uint8_t leds);
69 uint8_t matrix_rows(void)
75 uint8_t matrix_cols(void)
80 void matrix_init(void)
88 _ps2_set_leds(1<<PS2_LED_NUM_LOCK);
90 _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
92 _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
96 // initialize matrix state: all keys off
97 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
103 uint8_t matrix_scan(void)
111 // states for PrintScreen
117 // states for Pause/Break
124 E1_14_77_E1_F0_14_F0,
128 _matrix_is_modified = false;
130 // Pause/Break off(PS/2 has no break for this key)
131 if (matrix_is_on(_ROW(_PAUSE_BREAK), _COL(_PAUSE_BREAK))) {
132 _matrix_break(_PAUSE_BREAK);
136 while ((code = ps2_host_recv())) {
140 case 0xE0: // 2byte make
143 case 0xF0: // break code
146 case 0xE1: // Pause/Break
149 default: // normal key make
153 debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
160 case 0x12: // PrintScreen(make)
163 case 0x7C: // PrintScreen(typematic)
167 case 0xF0: // E0 break
172 _matrix_make(code|0x80);
174 debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
183 debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
187 case E0_F0: // E0 break
194 _matrix_break(code|0x80);
196 debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
201 /* PrintScreen(make) */
214 _matrix_make(_PRINT_SCREEN);
221 /* PrintScreen(break) */
234 state = E0_F0_7C_E0_F0;
243 _matrix_break(_PRINT_SCREEN);
281 state = E1_14_77_E1_F0;
290 state = E1_14_77_E1_F0_14;
296 case E1_14_77_E1_F0_14:
299 state = E1_14_77_E1_F0_14_F0;
305 case E1_14_77_E1_F0_14_F0:
308 _matrix_make(_PAUSE_BREAK);
320 static uint8_t prev_leds = 0;
321 if (prev_leds != usb_keyboard_leds) {
323 if (usb_keyboard_leds&(1<<USB_LED_SCROLL_LOCK))
324 leds |= (1<<PS2_LED_SCROLL_LOCK);
325 if (usb_keyboard_leds&(1<<USB_LED_NUM_LOCK))
326 leds |= (1<<PS2_LED_NUM_LOCK);
327 if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK))
328 leds |= (1<<PS2_LED_CAPS_LOCK);
331 prev_leds = usb_keyboard_leds;
337 bool matrix_is_modified(void)
339 return _matrix_is_modified;
343 bool matrix_has_ghost(void)
345 #ifdef MATRIX_HAS_GHOST
346 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
347 if (matrix_has_ghost_in_row(i))
355 bool matrix_is_on(uint8_t row, uint8_t col)
357 return (matrix[row] & (1<<col));
361 #if (MATRIX_COLS <= 8)
362 uint8_t matrix_get_row(uint8_t row)
364 uint16_t matrix_get_row(uint8_t row)
370 void matrix_print(void)
372 #if (MATRIX_COLS <= 8)
373 print("\nr/c 01234567\n");
375 print("\nr/c 0123456789ABCDEF\n");
377 for (uint8_t row = 0; row < matrix_rows(); row++) {
378 phex(row); print(": ");
379 #if (MATRIX_COLS <= 8)
380 pbin_reverse(matrix_get_row(row));
382 pbin_reverse16(matrix_get_row(row));
384 #ifdef MATRIX_HAS_GHOST
385 if (matrix_has_ghost_in_row(row)) {
393 uint8_t matrix_key_count(void)
396 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
397 #if (MATRIX_COLS <= 8)
398 count += bitpop(matrix[i]);
400 count += bitpop16(matrix[i]);
406 #ifdef MATRIX_HAS_GHOST
408 static bool matrix_has_ghost_in_row(uint8_t row)
410 // no ghost exists in case less than 2 keys on
411 if (((matrix[row] - 1) & matrix[row]) == 0)
414 // ghost exists in case same state as other row
415 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
416 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
425 static void _matrix_make(uint8_t code)
427 if (!matrix_is_on(_ROW(code), _COL(code))) {
428 matrix[_ROW(code)] |= 1<<_COL(code);
429 _matrix_is_modified = true;
434 static void _matrix_break(uint8_t code)
436 if (matrix_is_on(_ROW(code), _COL(code))) {
437 matrix[_ROW(code)] &= ~(1<<_COL(code));
438 _matrix_is_modified = true;
442 static void _ps2_reset(void)
445 ps2_host_recv(); // 0xFA
446 ps2_host_recv(); // 0xAA
450 static void _ps2_set_leds(uint8_t leds)
453 ps2_host_recv(); // 0xFA
455 ps2_host_recv(); // 0xFA