]>
git.gir.st - tmk_keyboard.git/blob - ps2_usb/matrix.c
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