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_ */