# HG changeset patch # User John Tsiombikas # Date 1507955027 -10800 # Node ID 3228a731d4db6c084501f8b53c926ac503ce55aa # Parent 8e8e17a0f88ed4c2dcd46ba38cca2246226dbb49 translate scancodes diff -r 8e8e17a0f88e -r 3228a731d4db Makefile --- a/Makefile Thu Oct 12 04:08:48 2017 +0300 +++ b/Makefile Sat Oct 14 07:23:47 2017 +0300 @@ -4,8 +4,8 @@ hex = $(bin).hex eep = $(bin).eep -mcu_gcc = atmega88 -mcu_dude = m88 +mcu_gcc = atmega168 +mcu_dude = m168 CC = avr-gcc OBJCOPY = avr-objcopy diff -r 8e8e17a0f88e -r 3228a731d4db src/main.c --- a/src/main.c Thu Oct 12 04:08:48 2017 +0300 +++ b/src/main.c Sat Oct 14 07:23:47 2017 +0300 @@ -1,16 +1,18 @@ #define F_CPU XTAL #include +#include #include #include #include #include #include "serial.h" +#include "scantbl.h" /* pin assignments: * B0 PS/2 data - * B1 PS/2 clock - * C0 KBD data - * C1 KBD clock + * D2 PS/2 clock (INT0) + * B1 KBD data + * D3 KBD clock (INT1) */ #define BIT_DATA 1 @@ -19,50 +21,86 @@ #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0) #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0) #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0) -#define PS2INTR_UNMASK do { PCICR |= (1 << PCIE0); } while(0) -#define PS2INTR_MASK do { PCICR &= ~(1 << PCIE0); } while(0) void ps2write(unsigned char c); -int ps2read(unsigned char *c); +unsigned char ps2read(void); +int ps2pending(void); +#define BUF_SZ 16 +#define BUF_IDX_MASK (BUF_SZ - 1) +#define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK) +static volatile unsigned char keybuf[BUF_SZ]; +static volatile unsigned char key_rd, key_wr; + +static volatile int sending; + +enum { + KF_BRK = 1, + KF_EXT = 2, + KF_EXT1 = 4, +}; int main(void) { - int led = 1, dir = 1; + unsigned int keyflags = 0; + int keycode; DDRB = 0; - DDRC = 0; + DDRD = 0; PORTB = 0; - PORTC = 0; + PORTD = 0; + EIMSK = 0; /* mask external interrupts */ + EICRA = (1 << ISC11) | (1 << ISC01); /* falling edge interrupts */ /* initialize the UART and enable interrupts */ init_serial(9600); sei(); printf("PS/2 keyboard controller - John Tsiombikas \r\n"); - fflush(stdout); + + EIMSK = (1 << INT0); /* enable ps/2 clock interrupt */ for(;;) { - printf("hello!\r\n"); - fflush(stdout); - unsigned char c; + unsigned char c = ps2read(); + switch(c) { + case 0xe0: /* extended */ + keyflags |= KF_EXT; + break; - ps2write(0xed); - ps2read(&c); - if(c != 0xfa) { - printf("expected ack, got: %xh\r\n", (unsigned int)c); - } else { - ps2write(led); - if(led == 1) dir = 1; - if(led == 7) dir = -1; + case 0xe1: /* extended */ + keyflags |= KF_EXT1; + break; - if(dir > 0) { - led <<= 1; + case 0xf0: /* break code */ + keyflags |= KF_BRK; + break; + + default: + keycode = 0; + if(keyflags & KF_EXT) { + printf("ext "); + if(c < KEYMAP_EXT_SIZE) { + keycode = keymap_ext[(int)c]; + } + } else if(keyflags & KF_EXT1) { + printf("ext1 "); } else { - led >>= 1; + if(c < KEYMAP_NORMAL_SIZE) { + keycode = keymap_normal[(int)c]; + } } - _delay_ms(1000); + if(keycode >= 256) { + /*printf("%s: %s (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", skeystr[keycode - 256], (unsigned int)c);*/ + printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c); + } else if(isprint(keycode)) { + printf("%s: %c (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", (char)keycode, (unsigned int)c); + } else if(keycode > 0) { + printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c); + } else { + printf("%s: %x\r\n", keyflags & KF_BRK ? "release" : "press", (unsigned int)c); + } + keyflags = 0; } } return 0; @@ -71,7 +109,7 @@ void ps2write(unsigned char c) { int i; - unsigned short out = (unsigned short)c | ((unsigned short)(~parity_even_bit(c) & 1) << 8); + unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8); /* pull clock low for >60us */ PS2LOW(BIT_CLK); @@ -82,39 +120,64 @@ PS2REL(BIT_CLK); for(i=0; i<9; i++) { - printf("bit %d: wait for clk-low\r\n", i); while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */ PORTB |= out & 1; out >>= 1; - printf("bit %d: wait for clk-high\r\n", i); while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */ } PS2REL(BIT_DATA); /* wait for ack */ - printf("wait for ack (low)\r\n"); while(PINB & BIT_DATA); - printf("wait for ack (high)\r\n"); while(!(PINB & BIT_DATA)); } -int ps2read(unsigned char *c) +unsigned char ps2read(void) { - int i, p; - unsigned short in = 0; + unsigned char key; - /* wait for kbd to drive the clock low for the start bit (blocks here) */ - while(PINB & BIT_CLK); - while(!(PINB & BIT_CLK)); - - for(i=0; i<9; i++) { - while(PINB & BIT_CLK); /* wait for clock to go low */ - in |= (PINB & 1) << i; - while(!(PINB & BIT_CLK)); + while(key_rd == key_wr) { } - p = ~parity_even_bit((unsigned char)in); - *c = in; + cli(); + key = keybuf[key_rd]; + key_rd = NEXT_IDX(key_rd); + sei(); - return (p == ((in >> 8) & 1)) ? 0 : -1; + return key; } + +int ps2pending(void) +{ + return key_rd != key_wr; +} + +ISR(INT0_vect) +{ + static unsigned char value, valp, parity; + static int nbits; + + if(sending) { + } else { + if(nbits > 0 && nbits < 9) { + value >>= 1; + if(PINB & 1) { + value |= 0x80; + parity ^= 1; + } + }/* else if(nbits == 9) { + valp = PINB & 1; + }*/ + if(++nbits >= 11) { + nbits = 0; + + /* check parity */ + /*if((parity & 1) == (valp & 1)) {}*/ + keybuf[key_wr] = (unsigned char)value; + key_wr = NEXT_IDX(key_wr); + + value = 0; + parity = 0; + } + } +} diff -r 8e8e17a0f88e -r 3228a731d4db src/scantbl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scantbl.h Sat Oct 14 07:23:47 2017 +0300 @@ -0,0 +1,87 @@ +#ifndef SCANTBL_H_ +#define SCANTBL_H_ + +enum { + KEY_ESC = 27, + + KEY_F1 = 256, + KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, + KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, KEY_BRK, + KEY_SCRLK, KEY_CAPSLK, KEY_NUMLK, + + KEY_LSHIFT, KEY_RSHIFT, + KEY_LCTRL, KEY_RCTRL, + KEY_LALT, KEY_RALT, + KEY_LWIN, KEY_RWIN, KEY_MENU, + + KEY_INS, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP, KEY_PGDOWN, + KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, + + KEY_KP_0, KEY_KP_1, KEY_KP_2, KEY_KP_3, KEY_KP_4, + KEY_KP_5, KEY_KP_6, KEY_KP_7, KEY_KP_8, KEY_KP_9, + KEY_KP_DIV, KEY_KP_MUL, KEY_KP_MINUS, KEY_KP_PLUS, + KEY_KP_DOT, KEY_KP_ENTER, + + KEY_MM_WWW_SEARCH, KEY_MM_WWW_FAV, KEY_MM_WWW_REFRESH, KEY_MM_WWW_STOP, + KEY_MM_WWW_FWD, KEY_MM_WWW_BACK, KEY_MM_WWW_HOME, + KEY_MM_PREV, KEY_MM_NEXT, KEY_MM_PLAY, KEY_MM_STOP, KEY_MM_VOLUP, KEY_MM_VOLDOWN, + KEY_MM_MUTE, KEY_MM_CALC, KEY_MM_MYCOMP, KEY_MM_EMAIL, KEY_MM_SELECT, + KEY_APPS, + KEY_ACPI_POWER, KEY_ACPI_SLEEP, KEY_ACPI_WAKEUP +}; + + +static const char *skeystr[] = { + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", + "SysRq", "Break", "Scroll Lock", "Caps Lock", "Num Lock", + "L Shift", "R Shift", "L Ctrl", "R Ctrl", "L Alt", "R Alt", "L Win", "R Win", "Menu", + "Insert", "Delete", "Home", "End", "Page Up", "Page Down", "Left", "Right", "Up", "Down", + "Keypad 0", "Keypad 1", "Keypad 2", "Keypad 3", "Keypad 4", "Keypad 5", "Keypad 6", + "Keypad 7", "Keypad 8", "Keypad 9", "Keypad /", "Keypad *", "Keypad -", "Keypad +", + "Keypad .", "Keypad Enter", + "WWW Search", "WWW Fav", "WWW Refresh", "WWW Stop", "WWW Fwd", "WWW Back", "WWW Home", + "Prev", "Next", "Play", "Stop", "Volume Up", "Volume Down", "Mute", "Calculator", + "My Computer", "Email", "Select Media", "Apps", + "Power", "Sleep", "Wakeup", +}; + + +#define KEYMAP_NORMAL_SIZE (sizeof keymap_normal / sizeof *keymap_normal) +static int keymap_normal[] = { + 0, KEY_F9, 0, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, /* 00 - 07 */ + 0, KEY_F10, KEY_F8, KEY_F6, KEY_F4, '\t', '`', 0, /* 08 - 0f */ + 0, KEY_LALT, KEY_LSHIFT, 0, KEY_LCTRL, 'q', '1', 0, /* 10 - 17 */ + 0, 0, 'z', 's', 'a', 'w', '2', 0, /* 18 - 1f */ + 0, 'c', 'x', 'd', 'e', '4', '3', 0, /* 20 - 27 */ + 0, ' ', 'v', 'f', 't', 'r', '5', 0, /* 28 - 2f */ + 0, 'n', 'b', 'h', 'g', 'y', '6', 0, /* 30 - 37 */ + 0, 0, 'm', 'j', 'u', '7', '8', 0, /* 38 - 3f */ + 0, ',', 'k', 'i', 'o', '0', '9', 0, /* 40 - 47 */ + 0, '.', '/', 'l', ';', 'p', '-', 0, /* 48 - 4f */ + 0, 0, '\'', 0, '[', '=', 0, 0, /* 50 - 57 */ + KEY_CAPSLK, KEY_RSHIFT, '\n', ']', 0, '\\', 0, 0, /* 58 - 5f */ + 0, 0, 0, 0, 0, 0, '\b', 0, /* 60 - 67 */ + 0, KEY_KP_1, 0, KEY_KP_4, KEY_KP_7, 0, 0, 0, /* 68 - 6f */ + KEY_KP_0, KEY_KP_DOT, KEY_KP_2, KEY_KP_5, KEY_KP_6, KEY_KP_8, KEY_ESC, KEY_NUMLK, /* 70 - 77 */ + KEY_F11, KEY_KP_PLUS, KEY_KP_3, KEY_KP_MINUS, KEY_KP_MUL, KEY_KP_9, KEY_SCRLK, 0,/* 78 - 7f */ + 0, 0, 0, KEY_F7 /* 80 - 83 */ +}; + +#define KEYMAP_EXT_SIZE (sizeof keymap_ext / sizeof *keymap_ext) +static int keymap_ext[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 08 - 0f */ + KEY_MM_WWW_SEARCH, KEY_RALT, 0, 0, KEY_RCTRL, KEY_MM_PREV, 0, 0, /* 10 - 17 */ + KEY_MM_WWW_FAV, 0, 0, 0, 0, 0, 0, KEY_LWIN, /* 18 - 1f */ + KEY_MM_WWW_REFRESH, KEY_MM_VOLDOWN, 0, KEY_MM_MUTE, 0, 0, 0, KEY_RWIN, /* 20 - 27 */ + KEY_MM_STOP, 0, 0, KEY_MM_CALC, 0, 0, 0, KEY_APPS, /* 28 - 2f */ + KEY_MM_WWW_FWD, 0, KEY_MM_VOLUP, 0, KEY_MM_PLAY, 0, 0, KEY_ACPI_POWER, /* 30 - 37 */ + KEY_MM_WWW_BACK, 0, KEY_MM_WWW_HOME, KEY_MM_STOP, 0, 0, 0, KEY_ACPI_SLEEP, /* 38 - 3f */ + KEY_MM_MYCOMP, 0, 0, 0, KEY_MM_EMAIL, 0, KEY_KP_DIV, 0, /* 40 - 47 */ + 0, KEY_MM_NEXT, 0, 0, KEY_MM_SELECT, 0, 0, 0, /* 48 - 4f */ + 0, 0, KEY_ACPI_WAKEUP, 0, 0, KEY_END, 0, KEY_LEFT, /* 50 - 57 */ + KEY_HOME, 0, 0, 0, KEY_INS, KEY_DEL, KEY_DOWN, 0, /* 58 - 5f */ + KEY_RIGHT, KEY_UP, 0, 0, 0, 0, KEY_DOWN, 0, /* 60 - 67 */ +}; + +#endif /* SCANTBL_H_ */