a500kbd
changeset 1:3228a731d4db
translate scancodes
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Oct 2017 07:23:47 +0300 |
parents | 8e8e17a0f88e |
children | a4fd9c5a6655 |
files | Makefile src/main.c src/scantbl.h |
diffstat | 3 files changed, 196 insertions(+), 46 deletions(-) [+] |
line diff
1.1 --- a/Makefile Thu Oct 12 04:08:48 2017 +0300 1.2 +++ b/Makefile Sat Oct 14 07:23:47 2017 +0300 1.3 @@ -4,8 +4,8 @@ 1.4 hex = $(bin).hex 1.5 eep = $(bin).eep 1.6 1.7 -mcu_gcc = atmega88 1.8 -mcu_dude = m88 1.9 +mcu_gcc = atmega168 1.10 +mcu_dude = m168 1.11 1.12 CC = avr-gcc 1.13 OBJCOPY = avr-objcopy
2.1 --- a/src/main.c Thu Oct 12 04:08:48 2017 +0300 2.2 +++ b/src/main.c Sat Oct 14 07:23:47 2017 +0300 2.3 @@ -1,16 +1,18 @@ 2.4 #define F_CPU XTAL 2.5 #include <stdio.h> 2.6 +#include <ctype.h> 2.7 #include <avr/io.h> 2.8 #include <avr/interrupt.h> 2.9 #include <util/delay.h> 2.10 #include <util/parity.h> 2.11 #include "serial.h" 2.12 +#include "scantbl.h" 2.13 2.14 /* pin assignments: 2.15 * B0 PS/2 data 2.16 - * B1 PS/2 clock 2.17 - * C0 KBD data 2.18 - * C1 KBD clock 2.19 + * D2 PS/2 clock (INT0) 2.20 + * B1 KBD data 2.21 + * D3 KBD clock (INT1) 2.22 */ 2.23 2.24 #define BIT_DATA 1 2.25 @@ -19,50 +21,86 @@ 2.26 #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0) 2.27 #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0) 2.28 #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0) 2.29 -#define PS2INTR_UNMASK do { PCICR |= (1 << PCIE0); } while(0) 2.30 -#define PS2INTR_MASK do { PCICR &= ~(1 << PCIE0); } while(0) 2.31 2.32 void ps2write(unsigned char c); 2.33 -int ps2read(unsigned char *c); 2.34 +unsigned char ps2read(void); 2.35 +int ps2pending(void); 2.36 2.37 +#define BUF_SZ 16 2.38 +#define BUF_IDX_MASK (BUF_SZ - 1) 2.39 +#define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK) 2.40 +static volatile unsigned char keybuf[BUF_SZ]; 2.41 +static volatile unsigned char key_rd, key_wr; 2.42 + 2.43 +static volatile int sending; 2.44 + 2.45 +enum { 2.46 + KF_BRK = 1, 2.47 + KF_EXT = 2, 2.48 + KF_EXT1 = 4, 2.49 +}; 2.50 2.51 int main(void) 2.52 { 2.53 - int led = 1, dir = 1; 2.54 + unsigned int keyflags = 0; 2.55 + int keycode; 2.56 2.57 DDRB = 0; 2.58 - DDRC = 0; 2.59 + DDRD = 0; 2.60 PORTB = 0; 2.61 - PORTC = 0; 2.62 + PORTD = 0; 2.63 + EIMSK = 0; /* mask external interrupts */ 2.64 + EICRA = (1 << ISC11) | (1 << ISC01); /* falling edge interrupts */ 2.65 2.66 /* initialize the UART and enable interrupts */ 2.67 init_serial(9600); 2.68 sei(); 2.69 2.70 printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n"); 2.71 - fflush(stdout); 2.72 + 2.73 + EIMSK = (1 << INT0); /* enable ps/2 clock interrupt */ 2.74 2.75 for(;;) { 2.76 - printf("hello!\r\n"); 2.77 - fflush(stdout); 2.78 - unsigned char c; 2.79 + unsigned char c = ps2read(); 2.80 + switch(c) { 2.81 + case 0xe0: /* extended */ 2.82 + keyflags |= KF_EXT; 2.83 + break; 2.84 2.85 - ps2write(0xed); 2.86 - ps2read(&c); 2.87 - if(c != 0xfa) { 2.88 - printf("expected ack, got: %xh\r\n", (unsigned int)c); 2.89 - } else { 2.90 - ps2write(led); 2.91 - if(led == 1) dir = 1; 2.92 - if(led == 7) dir = -1; 2.93 + case 0xe1: /* extended */ 2.94 + keyflags |= KF_EXT1; 2.95 + break; 2.96 2.97 - if(dir > 0) { 2.98 - led <<= 1; 2.99 + case 0xf0: /* break code */ 2.100 + keyflags |= KF_BRK; 2.101 + break; 2.102 + 2.103 + default: 2.104 + keycode = 0; 2.105 + if(keyflags & KF_EXT) { 2.106 + printf("ext "); 2.107 + if(c < KEYMAP_EXT_SIZE) { 2.108 + keycode = keymap_ext[(int)c]; 2.109 + } 2.110 + } else if(keyflags & KF_EXT1) { 2.111 + printf("ext1 "); 2.112 } else { 2.113 - led >>= 1; 2.114 + if(c < KEYMAP_NORMAL_SIZE) { 2.115 + keycode = keymap_normal[(int)c]; 2.116 + } 2.117 } 2.118 2.119 - _delay_ms(1000); 2.120 + if(keycode >= 256) { 2.121 + /*printf("%s: %s (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", skeystr[keycode - 256], (unsigned int)c);*/ 2.122 + printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c); 2.123 + } else if(isprint(keycode)) { 2.124 + printf("%s: %c (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", (char)keycode, (unsigned int)c); 2.125 + } else if(keycode > 0) { 2.126 + printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c); 2.127 + } else { 2.128 + printf("%s: %x\r\n", keyflags & KF_BRK ? "release" : "press", (unsigned int)c); 2.129 + } 2.130 + keyflags = 0; 2.131 } 2.132 } 2.133 return 0; 2.134 @@ -71,7 +109,7 @@ 2.135 void ps2write(unsigned char c) 2.136 { 2.137 int i; 2.138 - unsigned short out = (unsigned short)c | ((unsigned short)(~parity_even_bit(c) & 1) << 8); 2.139 + unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8); 2.140 2.141 /* pull clock low for >60us */ 2.142 PS2LOW(BIT_CLK); 2.143 @@ -82,39 +120,64 @@ 2.144 PS2REL(BIT_CLK); 2.145 2.146 for(i=0; i<9; i++) { 2.147 - printf("bit %d: wait for clk-low\r\n", i); 2.148 while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */ 2.149 PORTB |= out & 1; 2.150 out >>= 1; 2.151 - printf("bit %d: wait for clk-high\r\n", i); 2.152 while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */ 2.153 } 2.154 2.155 PS2REL(BIT_DATA); 2.156 /* wait for ack */ 2.157 - printf("wait for ack (low)\r\n"); 2.158 while(PINB & BIT_DATA); 2.159 - printf("wait for ack (high)\r\n"); 2.160 while(!(PINB & BIT_DATA)); 2.161 } 2.162 2.163 -int ps2read(unsigned char *c) 2.164 +unsigned char ps2read(void) 2.165 { 2.166 - int i, p; 2.167 - unsigned short in = 0; 2.168 + unsigned char key; 2.169 2.170 - /* wait for kbd to drive the clock low for the start bit (blocks here) */ 2.171 - while(PINB & BIT_CLK); 2.172 - while(!(PINB & BIT_CLK)); 2.173 - 2.174 - for(i=0; i<9; i++) { 2.175 - while(PINB & BIT_CLK); /* wait for clock to go low */ 2.176 - in |= (PINB & 1) << i; 2.177 - while(!(PINB & BIT_CLK)); 2.178 + while(key_rd == key_wr) { 2.179 } 2.180 2.181 - p = ~parity_even_bit((unsigned char)in); 2.182 - *c = in; 2.183 + cli(); 2.184 + key = keybuf[key_rd]; 2.185 + key_rd = NEXT_IDX(key_rd); 2.186 + sei(); 2.187 2.188 - return (p == ((in >> 8) & 1)) ? 0 : -1; 2.189 + return key; 2.190 } 2.191 + 2.192 +int ps2pending(void) 2.193 +{ 2.194 + return key_rd != key_wr; 2.195 +} 2.196 + 2.197 +ISR(INT0_vect) 2.198 +{ 2.199 + static unsigned char value, valp, parity; 2.200 + static int nbits; 2.201 + 2.202 + if(sending) { 2.203 + } else { 2.204 + if(nbits > 0 && nbits < 9) { 2.205 + value >>= 1; 2.206 + if(PINB & 1) { 2.207 + value |= 0x80; 2.208 + parity ^= 1; 2.209 + } 2.210 + }/* else if(nbits == 9) { 2.211 + valp = PINB & 1; 2.212 + }*/ 2.213 + if(++nbits >= 11) { 2.214 + nbits = 0; 2.215 + 2.216 + /* check parity */ 2.217 + /*if((parity & 1) == (valp & 1)) {}*/ 2.218 + keybuf[key_wr] = (unsigned char)value; 2.219 + key_wr = NEXT_IDX(key_wr); 2.220 + 2.221 + value = 0; 2.222 + parity = 0; 2.223 + } 2.224 + } 2.225 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/scantbl.h Sat Oct 14 07:23:47 2017 +0300 3.3 @@ -0,0 +1,87 @@ 3.4 +#ifndef SCANTBL_H_ 3.5 +#define SCANTBL_H_ 3.6 + 3.7 +enum { 3.8 + KEY_ESC = 27, 3.9 + 3.10 + KEY_F1 = 256, 3.11 + KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, 3.12 + KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, KEY_BRK, 3.13 + KEY_SCRLK, KEY_CAPSLK, KEY_NUMLK, 3.14 + 3.15 + KEY_LSHIFT, KEY_RSHIFT, 3.16 + KEY_LCTRL, KEY_RCTRL, 3.17 + KEY_LALT, KEY_RALT, 3.18 + KEY_LWIN, KEY_RWIN, KEY_MENU, 3.19 + 3.20 + KEY_INS, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP, KEY_PGDOWN, 3.21 + KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, 3.22 + 3.23 + KEY_KP_0, KEY_KP_1, KEY_KP_2, KEY_KP_3, KEY_KP_4, 3.24 + KEY_KP_5, KEY_KP_6, KEY_KP_7, KEY_KP_8, KEY_KP_9, 3.25 + KEY_KP_DIV, KEY_KP_MUL, KEY_KP_MINUS, KEY_KP_PLUS, 3.26 + KEY_KP_DOT, KEY_KP_ENTER, 3.27 + 3.28 + KEY_MM_WWW_SEARCH, KEY_MM_WWW_FAV, KEY_MM_WWW_REFRESH, KEY_MM_WWW_STOP, 3.29 + KEY_MM_WWW_FWD, KEY_MM_WWW_BACK, KEY_MM_WWW_HOME, 3.30 + KEY_MM_PREV, KEY_MM_NEXT, KEY_MM_PLAY, KEY_MM_STOP, KEY_MM_VOLUP, KEY_MM_VOLDOWN, 3.31 + KEY_MM_MUTE, KEY_MM_CALC, KEY_MM_MYCOMP, KEY_MM_EMAIL, KEY_MM_SELECT, 3.32 + KEY_APPS, 3.33 + KEY_ACPI_POWER, KEY_ACPI_SLEEP, KEY_ACPI_WAKEUP 3.34 +}; 3.35 + 3.36 + 3.37 +static const char *skeystr[] = { 3.38 + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", 3.39 + "SysRq", "Break", "Scroll Lock", "Caps Lock", "Num Lock", 3.40 + "L Shift", "R Shift", "L Ctrl", "R Ctrl", "L Alt", "R Alt", "L Win", "R Win", "Menu", 3.41 + "Insert", "Delete", "Home", "End", "Page Up", "Page Down", "Left", "Right", "Up", "Down", 3.42 + "Keypad 0", "Keypad 1", "Keypad 2", "Keypad 3", "Keypad 4", "Keypad 5", "Keypad 6", 3.43 + "Keypad 7", "Keypad 8", "Keypad 9", "Keypad /", "Keypad *", "Keypad -", "Keypad +", 3.44 + "Keypad .", "Keypad Enter", 3.45 + "WWW Search", "WWW Fav", "WWW Refresh", "WWW Stop", "WWW Fwd", "WWW Back", "WWW Home", 3.46 + "Prev", "Next", "Play", "Stop", "Volume Up", "Volume Down", "Mute", "Calculator", 3.47 + "My Computer", "Email", "Select Media", "Apps", 3.48 + "Power", "Sleep", "Wakeup", 3.49 +}; 3.50 + 3.51 + 3.52 +#define KEYMAP_NORMAL_SIZE (sizeof keymap_normal / sizeof *keymap_normal) 3.53 +static int keymap_normal[] = { 3.54 + 0, KEY_F9, 0, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, /* 00 - 07 */ 3.55 + 0, KEY_F10, KEY_F8, KEY_F6, KEY_F4, '\t', '`', 0, /* 08 - 0f */ 3.56 + 0, KEY_LALT, KEY_LSHIFT, 0, KEY_LCTRL, 'q', '1', 0, /* 10 - 17 */ 3.57 + 0, 0, 'z', 's', 'a', 'w', '2', 0, /* 18 - 1f */ 3.58 + 0, 'c', 'x', 'd', 'e', '4', '3', 0, /* 20 - 27 */ 3.59 + 0, ' ', 'v', 'f', 't', 'r', '5', 0, /* 28 - 2f */ 3.60 + 0, 'n', 'b', 'h', 'g', 'y', '6', 0, /* 30 - 37 */ 3.61 + 0, 0, 'm', 'j', 'u', '7', '8', 0, /* 38 - 3f */ 3.62 + 0, ',', 'k', 'i', 'o', '0', '9', 0, /* 40 - 47 */ 3.63 + 0, '.', '/', 'l', ';', 'p', '-', 0, /* 48 - 4f */ 3.64 + 0, 0, '\'', 0, '[', '=', 0, 0, /* 50 - 57 */ 3.65 + KEY_CAPSLK, KEY_RSHIFT, '\n', ']', 0, '\\', 0, 0, /* 58 - 5f */ 3.66 + 0, 0, 0, 0, 0, 0, '\b', 0, /* 60 - 67 */ 3.67 + 0, KEY_KP_1, 0, KEY_KP_4, KEY_KP_7, 0, 0, 0, /* 68 - 6f */ 3.68 + KEY_KP_0, KEY_KP_DOT, KEY_KP_2, KEY_KP_5, KEY_KP_6, KEY_KP_8, KEY_ESC, KEY_NUMLK, /* 70 - 77 */ 3.69 + KEY_F11, KEY_KP_PLUS, KEY_KP_3, KEY_KP_MINUS, KEY_KP_MUL, KEY_KP_9, KEY_SCRLK, 0,/* 78 - 7f */ 3.70 + 0, 0, 0, KEY_F7 /* 80 - 83 */ 3.71 +}; 3.72 + 3.73 +#define KEYMAP_EXT_SIZE (sizeof keymap_ext / sizeof *keymap_ext) 3.74 +static int keymap_ext[] = { 3.75 + 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ 3.76 + 0, 0, 0, 0, 0, 0, 0, 0, /* 08 - 0f */ 3.77 + KEY_MM_WWW_SEARCH, KEY_RALT, 0, 0, KEY_RCTRL, KEY_MM_PREV, 0, 0, /* 10 - 17 */ 3.78 + KEY_MM_WWW_FAV, 0, 0, 0, 0, 0, 0, KEY_LWIN, /* 18 - 1f */ 3.79 + KEY_MM_WWW_REFRESH, KEY_MM_VOLDOWN, 0, KEY_MM_MUTE, 0, 0, 0, KEY_RWIN, /* 20 - 27 */ 3.80 + KEY_MM_STOP, 0, 0, KEY_MM_CALC, 0, 0, 0, KEY_APPS, /* 28 - 2f */ 3.81 + KEY_MM_WWW_FWD, 0, KEY_MM_VOLUP, 0, KEY_MM_PLAY, 0, 0, KEY_ACPI_POWER, /* 30 - 37 */ 3.82 + KEY_MM_WWW_BACK, 0, KEY_MM_WWW_HOME, KEY_MM_STOP, 0, 0, 0, KEY_ACPI_SLEEP, /* 38 - 3f */ 3.83 + KEY_MM_MYCOMP, 0, 0, 0, KEY_MM_EMAIL, 0, KEY_KP_DIV, 0, /* 40 - 47 */ 3.84 + 0, KEY_MM_NEXT, 0, 0, KEY_MM_SELECT, 0, 0, 0, /* 48 - 4f */ 3.85 + 0, 0, KEY_ACPI_WAKEUP, 0, 0, KEY_END, 0, KEY_LEFT, /* 50 - 57 */ 3.86 + KEY_HOME, 0, 0, 0, KEY_INS, KEY_DEL, KEY_DOWN, 0, /* 58 - 5f */ 3.87 + KEY_RIGHT, KEY_UP, 0, 0, 0, 0, KEY_DOWN, 0, /* 60 - 67 */ 3.88 +}; 3.89 + 3.90 +#endif /* SCANTBL_H_ */