changed names which does not comply to C spec.(underscore prefix names)tags/v1.9
// Convert physical keyboard layout to matrix array. | // Convert physical keyboard layout to matrix array. | ||||
// This is a macro to define keymap easily in keyboard layout form. | // This is a macro to define keymap easily in keyboard layout form. | ||||
#define KEYMAP( \ | #define KEYMAP( \ | ||||
K76, K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFE,K7E,KFF, KB7,KBF,KDE, \ | |||||
K76, K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFC,K7E,KFE, KB7,KBF,KDE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | ||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | ||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | ||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | ||||
{ KB_NO, KB_##KE9, KB_NO, KB_##KEB, KB_##KEC, KB_NO, KB_NO, KB_NO }, \ | { KB_NO, KB_##KE9, KB_NO, KB_##KEB, KB_##KEC, KB_NO, KB_NO, KB_NO }, \ | ||||
{ KB_##KF0, KB_##KF1, KB_##KF2, KB_NO, KB_##KF4, KB_##KF5, KB_NO, KB_NO }, \ | { KB_##KF0, KB_##KF1, KB_##KF2, KB_NO, KB_##KF4, KB_##KF5, KB_NO, KB_NO }, \ | ||||
{ KB_NO, KB_NO, KB_##KFA, KB_NO, KB_NO, KB_##KFD, KB_##KFE, KB_##KFF }, \ | |||||
{ KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \ | |||||
} | } | ||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | ||||
TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, | TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, | ||||
CAPS,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, | CAPS,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, | ||||
LSFT,VOLD,VOLU,MUTE,NO, NO, HOME,PGUP,PGDN,END, FN1, RSFT, UP, P1, P2, P3, | |||||
LSFT,VOLD,VOLU,MUTE,NO, NO, HOME,PGDN,PGUP,END, FN1, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | ||||
), | ), | ||||
}; | }; |
* 8bit | * 8bit | ||||
* --------- | * --------- | ||||
* 0| | | * 0| | | ||||
* :| XX | 00-7F for normal codes | |||||
* :| XX | 00-7F for normal codes(without E0-prefix) | |||||
* f|_________| | * f|_________| | ||||
* 10| | | * 10| | | ||||
* :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code) | * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code) | ||||
* 1f| | | * 1f| | | ||||
* --------- | * --------- | ||||
* exceptions: | * exceptions: | ||||
* 0x83: F8(normal code placed beyond 0x7F) | |||||
* 0xFE: PrintScreen | |||||
* 0xFF: Puause/Break | |||||
* 83: F8[0x83](normal codes but > 0x7F) | |||||
* FC: PrintScreen[E0 7C or 84] | |||||
* FE: Puause | |||||
*/ | */ | ||||
#define _PRINT_SCREEN (0xFE) | |||||
#define _PAUSE_BREAK (0xFF) | |||||
#define _ROW(code) (code>>3) | |||||
#define _COL(code) (code&0x07) | |||||
#define F8 (0x83) | |||||
#define PRINT_SCREEN (0xFC) | |||||
#define PAUSE (0xFE) | |||||
#define ROW(code) (code>>3) | |||||
#define COL(code) (code&0x07) | |||||
static bool _matrix_is_modified = false; | |||||
static bool is_modified = false; | |||||
// matrix state buffer(1:on, 0:off) | // matrix state buffer(1:on, 0:off) | ||||
#if (MATRIX_COLS <= 8) | #if (MATRIX_COLS <= 8) | ||||
static uint8_t *matrix; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
static uint8_t matrix[MATRIX_ROWS]; | |||||
#else | #else | ||||
static uint16_t *matrix; | |||||
static uint16_t _matrix0[MATRIX_ROWS]; | |||||
static uint16_t matrix[MATRIX_ROWS]; | |||||
#endif | #endif | ||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
static bool matrix_has_ghost_in_row(uint8_t row); | static bool matrix_has_ghost_in_row(uint8_t row); | ||||
#endif | #endif | ||||
static void _matrix_make(uint8_t code); | |||||
static void _matrix_break(uint8_t code); | |||||
static void _ps2_reset(void); | |||||
static void _ps2_set_leds(uint8_t leds); | |||||
static void matrix_make(uint8_t code); | |||||
static void matrix_break(uint8_t code); | |||||
static void ps2_reset(void); | |||||
static void ps2_set_leds(uint8_t leds); | |||||
inline | inline | ||||
print_enable = true; | print_enable = true; | ||||
ps2_host_init(); | ps2_host_init(); | ||||
_ps2_reset(); | |||||
ps2_reset(); | |||||
// flush LEDs | // flush LEDs | ||||
_ps2_set_leds(1<<PS2_LED_NUM_LOCK); | |||||
ps2_set_leds(1<<PS2_LED_NUM_LOCK); | |||||
_delay_ms(100); | _delay_ms(100); | ||||
_ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK); | |||||
ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK); | |||||
_delay_ms(100); | _delay_ms(100); | ||||
_ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK); | |||||
ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK); | |||||
_delay_ms(300); | _delay_ms(300); | ||||
_ps2_set_leds(0x00); | |||||
ps2_set_leds(0x00); | |||||
// initialize matrix state: all keys off | // initialize matrix state: all keys off | ||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
matrix = _matrix0; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
return; | return; | ||||
} | } | ||||
/* | |||||
* PS/2 Scan Code Set 2: Exceptional Handling | |||||
* | |||||
* There are several keys to be handled exceptionally. | |||||
* The scan code for these keys are varied or prefix/postfix'd | |||||
* depending on modifier key state. | |||||
* | |||||
* References: | |||||
* http://www.microsoft.com/whdc/archive/scancode.mspx | |||||
* http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc | |||||
* | |||||
* | |||||
* Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left: | |||||
* Num Lock: off | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Ohter | <make> | <break> | |||||
* LShift | E0 F0 12 <make> | <break> E0 12 | |||||
* RShift | E0 F0 59 <make> | <break> E0 59 | |||||
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 | |||||
* | |||||
* Num Lock: on | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Other | E0 12 <make> | <break> E0 F0 12 | |||||
* Shift'd | <make> | <break> | |||||
* | |||||
* Handling: ignore these prefix/postfix codes | |||||
* | |||||
* | |||||
* Keypad-/: | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Ohter | <make> | <break> | |||||
* LShift | E0 F0 12 <make> | <break> E0 12 | |||||
* RShift | E0 F0 59 <make> | <break> E0 59 | |||||
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 | |||||
* | |||||
* Handling: ignore these prefix/postfix codes | |||||
* | |||||
* | |||||
* PrintScreen: | |||||
* With hoding down modifiers, the scan code is sent as following: | |||||
* | |||||
* modifiers | make | break | |||||
* ----------+--------------+----------------------------------- | |||||
* Other | E0 12 E0 7C | E0 F0 7C E0 F0 12 | |||||
* Shift'd | E0 7C | E0 F0 7C | |||||
* Control'd | E0 7C | E0 F0 7C | |||||
* Alt'd | 84 | F0 84 | |||||
* | |||||
* Handling: ignore prefix/postfix codes and treat both scan code | |||||
* E0 7C and 84 as PrintScreen. | |||||
* | |||||
* Pause: | |||||
* With hoding down modifiers, the scan code is sent as following: | |||||
* | |||||
* modifiers | make(no break code) | |||||
* ----------+-------------------------------------------------- | |||||
* no mods | E1 14 77 E1 F0 14 F0 77 | |||||
* Control'd | E0 7E E0 F0 7E | |||||
* | |||||
* Handling: treat these two code sequence as Pause | |||||
* | |||||
*/ | |||||
uint8_t matrix_scan(void) | uint8_t matrix_scan(void) | ||||
{ | { | ||||
static enum { | static enum { | ||||
INIT, | INIT, | ||||
BREAK, | |||||
F0, | |||||
E0, | E0, | ||||
E0_F0, | E0_F0, | ||||
// states for PrintScreen | |||||
E0_12, | |||||
E0_12_E0, | |||||
E0_F0_7C, | |||||
E0_F0_7C_E0, | |||||
E0_F0_7C_E0_F0, | |||||
// states for Pause/Break | // states for Pause/Break | ||||
E1, | E1, | ||||
E1_14, | E1_14, | ||||
} state = INIT; | } state = INIT; | ||||
_matrix_is_modified = false; | |||||
is_modified = false; | |||||
// Pause/Break off(PS/2 has no break for this key) | // Pause/Break off(PS/2 has no break for this key) | ||||
if (matrix_is_on(_ROW(_PAUSE_BREAK), _COL(_PAUSE_BREAK))) { | |||||
_matrix_break(_PAUSE_BREAK); | |||||
if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) { | |||||
matrix_break(PAUSE); | |||||
} | } | ||||
uint8_t code; | uint8_t code; | ||||
while ((code = ps2_host_recv())) { | while ((code = ps2_host_recv())) { | ||||
debug_hex(code); debug(" "); | |||||
switch (state) { | switch (state) { | ||||
case INIT: | case INIT: | ||||
switch (code) { | switch (code) { | ||||
state = E0; | state = E0; | ||||
break; | break; | ||||
case 0xF0: // break code | case 0xF0: // break code | ||||
state = BREAK; | |||||
state = F0; | |||||
break; | break; | ||||
case 0xE1: // Pause/Break | case 0xE1: // Pause/Break | ||||
state = E1; | state = E1; | ||||
break; | break; | ||||
case 0x83: // F8 | |||||
matrix_make(F8); | |||||
state = INIT; | |||||
break; | |||||
case 0x84: // PrintScreen | |||||
matrix_make(PRINT_SCREEN); | |||||
state = INIT; | |||||
break; | |||||
default: // normal key make | default: // normal key make | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
_matrix_make(code); | |||||
matrix_make(code); | |||||
} else { | } else { | ||||
debug("ps/2 unknow code: "); debug_hex(code); debug("\n"); | |||||
debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n"); | |||||
} | } | ||||
state = INIT; | state = INIT; | ||||
} | } | ||||
break; | break; | ||||
case E0: | case E0: | ||||
switch (code) { | switch (code) { | ||||
case 0x12: // PrintScreen(make) | |||||
state = E0_12; | |||||
break; | |||||
case 0x7C: // PrintScreen(typematic) | |||||
case 0x12: // postfix/postfix code for exceptional keys | |||||
case 0x59: // postfix/postfix code for exceptional keys | |||||
// ignore | // ignore | ||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
case 0x7E: // former part of Control-Pause[E0 7E E0 F0 7E] | |||||
matrix_make(PAUSE); | |||||
state = INIT; | |||||
break; | |||||
case 0xF0: // E0 break | case 0xF0: // E0 break | ||||
state = E0_F0; | state = E0_F0; | ||||
break; | break; | ||||
default: // E0 make | default: // E0 make | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
_matrix_make(code|0x80); | |||||
} else { | |||||
debug("ps/2 unknow code: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case BREAK: | |||||
if (code < 0x80) { | |||||
_matrix_break(code); | |||||
} else { | |||||
debug("ps/2 unknow code: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
break; | |||||
case E0_F0: // E0 break | |||||
switch (code) { | |||||
case 0x7C: | |||||
state = E0_F0_7C; | |||||
break; | |||||
default: | |||||
if (code < 0x80) { | |||||
_matrix_break(code|0x80); | |||||
matrix_make(code|0x80); | |||||
} else { | } else { | ||||
debug("ps/2 unknow code: "); debug_hex(code); debug("\n"); | |||||
debug("unexpected scan code at E0: "); debug_hex(code); debug("\n"); | |||||
} | } | ||||
state = INIT; | state = INIT; | ||||
} | } | ||||
break; | break; | ||||
/* PrintScreen(make) */ | |||||
case E0_12: | |||||
case F0: | |||||
switch (code) { | switch (code) { | ||||
case 0xE0: | |||||
state = E0_12_E0; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E0_12_E0: | |||||
switch (code) { | |||||
case 0x7C: | |||||
_matrix_make(_PRINT_SCREEN); | |||||
case 0x83: | |||||
matrix_break(F8); | |||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
default: | |||||
case 0x84: | |||||
matrix_break(PRINT_SCREEN); | |||||
state = INIT; | state = INIT; | ||||
} | |||||
break; | |||||
/* PrintScreen(break) */ | |||||
case E0_F0_7C: | |||||
switch (code) { | |||||
case 0xE0: | |||||
state = E0_F0_7C_E0; | |||||
break; | break; | ||||
default: | default: | ||||
state = INIT; | |||||
if (code < 0x80) { | |||||
matrix_break(code); | |||||
} else { | |||||
debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | } | ||||
break; | break; | ||||
case E0_F0_7C_E0: | |||||
switch (code) { | |||||
case 0xF0: | |||||
state = E0_F0_7C_E0_F0; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E0_F0_7C_E0_F0: | |||||
case E0_F0: // E0 break | |||||
switch (code) { | switch (code) { | ||||
case 0x12: | |||||
_matrix_break(_PRINT_SCREEN); | |||||
case 0x12: // postfix/postfix code for exceptional keys | |||||
case 0x59: // postfix/postfix code for exceptional keys | |||||
case 0x7E: // latter part of Control-Pause[E0 7E E0 F0 7E] | |||||
// ignore | |||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
default: | default: | ||||
if (code < 0x80) { | |||||
matrix_break(code|0x80); | |||||
} else { | |||||
debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | state = INIT; | ||||
} | } | ||||
break; | break; | ||||
/* Pause/Break */ | |||||
/* Pause */ | |||||
case E1: | case E1: | ||||
switch (code) { | switch (code) { | ||||
case 0x14: | case 0x14: | ||||
case E1_14_77_E1_F0_14_F0: | case E1_14_77_E1_F0_14_F0: | ||||
switch (code) { | switch (code) { | ||||
case 0x77: | case 0x77: | ||||
_matrix_make(_PAUSE_BREAK); | |||||
matrix_make(PAUSE); | |||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
default: | default: | ||||
} | } | ||||
} | } | ||||
// handle LED indicators | |||||
static uint8_t prev_leds = 0; | static uint8_t prev_leds = 0; | ||||
if (prev_leds != usb_keyboard_leds) { | if (prev_leds != usb_keyboard_leds) { | ||||
uint8_t leds = 0; | uint8_t leds = 0; | ||||
if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK)) | if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK)) | ||||
leds |= (1<<PS2_LED_CAPS_LOCK); | leds |= (1<<PS2_LED_CAPS_LOCK); | ||||
_ps2_set_leds(leds); | |||||
ps2_set_leds(leds); | |||||
prev_leds = usb_keyboard_leds; | prev_leds = usb_keyboard_leds; | ||||
} | } | ||||
bool matrix_is_modified(void) | bool matrix_is_modified(void) | ||||
{ | { | ||||
return _matrix_is_modified; | |||||
return is_modified; | |||||
} | } | ||||
inline | inline | ||||
inline | inline | ||||
static void _matrix_make(uint8_t code) | |||||
static void matrix_make(uint8_t code) | |||||
{ | { | ||||
if (!matrix_is_on(_ROW(code), _COL(code))) { | |||||
matrix[_ROW(code)] |= 1<<_COL(code); | |||||
_matrix_is_modified = true; | |||||
if (!matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] |= 1<<COL(code); | |||||
is_modified = true; | |||||
} | } | ||||
} | } | ||||
inline | inline | ||||
static void _matrix_break(uint8_t code) | |||||
static void matrix_break(uint8_t code) | |||||
{ | { | ||||
if (matrix_is_on(_ROW(code), _COL(code))) { | |||||
matrix[_ROW(code)] &= ~(1<<_COL(code)); | |||||
_matrix_is_modified = true; | |||||
if (matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||||
is_modified = true; | |||||
} | } | ||||
} | } | ||||
static void _ps2_reset(void) | |||||
static void ps2_reset(void) | |||||
{ | { | ||||
ps2_host_send(0xFF); | ps2_host_send(0xFF); | ||||
ps2_host_recv(); // 0xFA | ps2_host_recv(); // 0xFA | ||||
_delay_ms(1000); | _delay_ms(1000); | ||||
} | } | ||||
static void _ps2_set_leds(uint8_t leds) | |||||
static void ps2_set_leds(uint8_t leds) | |||||
{ | { | ||||
ps2_host_send(0xED); | ps2_host_send(0xED); | ||||
ps2_host_recv(); // 0xFA | ps2_host_recv(); // 0xFA |