a500kbd

diff src/main.c @ 1:3228a731d4db

translate scancodes
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Oct 2017 07:23:47 +0300
parents 8e8e17a0f88e
children a4fd9c5a6655
line diff
     1.1 --- a/src/main.c	Thu Oct 12 04:08:48 2017 +0300
     1.2 +++ b/src/main.c	Sat Oct 14 07:23:47 2017 +0300
     1.3 @@ -1,16 +1,18 @@
     1.4  #define F_CPU	XTAL
     1.5  #include <stdio.h>
     1.6 +#include <ctype.h>
     1.7  #include <avr/io.h>
     1.8  #include <avr/interrupt.h>
     1.9  #include <util/delay.h>
    1.10  #include <util/parity.h>
    1.11  #include "serial.h"
    1.12 +#include "scantbl.h"
    1.13  
    1.14  /* pin assignments:
    1.15   * B0	PS/2 data
    1.16 - * B1	PS/2 clock
    1.17 - * C0	KBD data
    1.18 - * C1	KBD clock
    1.19 + * D2	PS/2 clock (INT0)
    1.20 + * B1	KBD data
    1.21 + * D3	KBD clock (INT1)
    1.22   */
    1.23  
    1.24  #define BIT_DATA	1
    1.25 @@ -19,50 +21,86 @@
    1.26  #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0)
    1.27  #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0)
    1.28  #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0)
    1.29 -#define PS2INTR_UNMASK do { PCICR |= (1 << PCIE0); } while(0)
    1.30 -#define PS2INTR_MASK do { PCICR &= ~(1 << PCIE0); } while(0)
    1.31  
    1.32  void ps2write(unsigned char c);
    1.33 -int ps2read(unsigned char *c);
    1.34 +unsigned char ps2read(void);
    1.35 +int ps2pending(void);
    1.36  
    1.37 +#define BUF_SZ	16
    1.38 +#define BUF_IDX_MASK	(BUF_SZ - 1)
    1.39 +#define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK)
    1.40 +static volatile unsigned char keybuf[BUF_SZ];
    1.41 +static volatile unsigned char key_rd, key_wr;
    1.42 +
    1.43 +static volatile int sending;
    1.44 +
    1.45 +enum {
    1.46 +	KF_BRK = 1,
    1.47 +	KF_EXT = 2,
    1.48 +	KF_EXT1 = 4,
    1.49 +};
    1.50  
    1.51  int main(void)
    1.52  {
    1.53 -	int led = 1, dir = 1;
    1.54 +	unsigned int keyflags = 0;
    1.55 +	int keycode;
    1.56  
    1.57  	DDRB = 0;
    1.58 -	DDRC = 0;
    1.59 +	DDRD = 0;
    1.60  	PORTB = 0;
    1.61 -	PORTC = 0;
    1.62 +	PORTD = 0;
    1.63 +	EIMSK = 0;	/* mask external interrupts */
    1.64 +	EICRA = (1 << ISC11) | (1 << ISC01);	/* falling edge interrupts */
    1.65  
    1.66  	/* initialize the UART and enable interrupts */
    1.67  	init_serial(9600);
    1.68  	sei();
    1.69  
    1.70  	printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n");
    1.71 -	fflush(stdout);
    1.72 +
    1.73 +	EIMSK = (1 << INT0);	/* enable ps/2 clock interrupt */
    1.74  
    1.75  	for(;;) {
    1.76 -		printf("hello!\r\n");
    1.77 -		fflush(stdout);
    1.78 -		unsigned char c;
    1.79 +		unsigned char c = ps2read();
    1.80 +		switch(c) {
    1.81 +		case 0xe0:	/* extended */
    1.82 +			keyflags |= KF_EXT;
    1.83 +			break;
    1.84  
    1.85 -		ps2write(0xed);
    1.86 -		ps2read(&c);
    1.87 -		if(c != 0xfa) {
    1.88 -			printf("expected ack, got: %xh\r\n", (unsigned int)c);
    1.89 -		} else {
    1.90 -			ps2write(led);
    1.91 -			if(led == 1) dir = 1;
    1.92 -			if(led == 7) dir = -1;
    1.93 +		case 0xe1:	/* extended */
    1.94 +			keyflags |= KF_EXT1;
    1.95 +			break;
    1.96  
    1.97 -			if(dir > 0) {
    1.98 -				led <<= 1;
    1.99 +		case 0xf0:	/* break code */
   1.100 +			keyflags |= KF_BRK;
   1.101 +			break;
   1.102 +
   1.103 +		default:
   1.104 +			keycode = 0;
   1.105 +			if(keyflags & KF_EXT) {
   1.106 +				printf("ext ");
   1.107 +				if(c < KEYMAP_EXT_SIZE) {
   1.108 +					keycode = keymap_ext[(int)c];
   1.109 +				}
   1.110 +			} else if(keyflags & KF_EXT1) {
   1.111 +				printf("ext1 ");
   1.112  			} else {
   1.113 -				led >>= 1;
   1.114 +				if(c < KEYMAP_NORMAL_SIZE) {
   1.115 +					keycode = keymap_normal[(int)c];
   1.116 +				}
   1.117  			}
   1.118  
   1.119 -			_delay_ms(1000);
   1.120 +			if(keycode >= 256) {
   1.121 +				/*printf("%s: %s (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", skeystr[keycode - 256], (unsigned int)c);*/
   1.122 +				printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
   1.123 +			} else if(isprint(keycode)) {
   1.124 +				printf("%s: %c (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", (char)keycode, (unsigned int)c);
   1.125 +			} else if(keycode > 0) {
   1.126 +				printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
   1.127 +			} else {
   1.128 +				printf("%s: %x\r\n", keyflags & KF_BRK ? "release" : "press", (unsigned int)c);
   1.129 +			}
   1.130 +			keyflags = 0;
   1.131  		}
   1.132  	}
   1.133  	return 0;
   1.134 @@ -71,7 +109,7 @@
   1.135  void ps2write(unsigned char c)
   1.136  {
   1.137  	int i;
   1.138 -	unsigned short out = (unsigned short)c | ((unsigned short)(~parity_even_bit(c) & 1) << 8);
   1.139 +	unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8);
   1.140  
   1.141  	/* pull clock low for >60us */
   1.142  	PS2LOW(BIT_CLK);
   1.143 @@ -82,39 +120,64 @@
   1.144  	PS2REL(BIT_CLK);
   1.145  
   1.146  	for(i=0; i<9; i++) {
   1.147 -		printf("bit %d: wait for clk-low\r\n", i);
   1.148  		while(PINB & BIT_CLK);	/* wait for kbd to drive the clock low */
   1.149  		PORTB |= out & 1;
   1.150  		out >>= 1;
   1.151 -		printf("bit %d: wait for clk-high\r\n", i);
   1.152  		while(!(PINB & BIT_CLK));	/* wait for kbd to drive the clock high */
   1.153  	}
   1.154  
   1.155  	PS2REL(BIT_DATA);
   1.156  	/* wait for ack */
   1.157 -	printf("wait for ack (low)\r\n");
   1.158  	while(PINB & BIT_DATA);
   1.159 -	printf("wait for ack (high)\r\n");
   1.160  	while(!(PINB & BIT_DATA));
   1.161  }
   1.162  
   1.163 -int ps2read(unsigned char *c)
   1.164 +unsigned char ps2read(void)
   1.165  {
   1.166 -	int i, p;
   1.167 -	unsigned short in = 0;
   1.168 +	unsigned char key;
   1.169  
   1.170 -	/* wait for kbd to drive the clock low for the start bit (blocks here) */
   1.171 -	while(PINB & BIT_CLK);
   1.172 -	while(!(PINB & BIT_CLK));
   1.173 -
   1.174 -	for(i=0; i<9; i++) {
   1.175 -		while(PINB & BIT_CLK);	/* wait for clock to go low */
   1.176 -		in |= (PINB & 1) << i;
   1.177 -		while(!(PINB & BIT_CLK));
   1.178 +	while(key_rd == key_wr) {
   1.179  	}
   1.180  
   1.181 -	p = ~parity_even_bit((unsigned char)in);
   1.182 -	*c = in;
   1.183 +	cli();
   1.184 +	key = keybuf[key_rd];
   1.185 +	key_rd = NEXT_IDX(key_rd);
   1.186 +	sei();
   1.187  
   1.188 -	return (p == ((in >> 8) & 1)) ? 0 : -1;
   1.189 +	return key;
   1.190  }
   1.191 +
   1.192 +int ps2pending(void)
   1.193 +{
   1.194 +	return key_rd != key_wr;
   1.195 +}
   1.196 +
   1.197 +ISR(INT0_vect)
   1.198 +{
   1.199 +	static unsigned char value, valp, parity;
   1.200 +	static int nbits;
   1.201 +
   1.202 +	if(sending) {
   1.203 +	} else {
   1.204 +		if(nbits > 0 && nbits < 9) {
   1.205 +			value >>= 1;
   1.206 +			if(PINB & 1) {
   1.207 +				value |= 0x80;
   1.208 +				parity ^= 1;
   1.209 +			}
   1.210 +		}/* else if(nbits == 9) {
   1.211 +			valp = PINB & 1;
   1.212 +		}*/
   1.213 +		if(++nbits >= 11) {
   1.214 +			nbits = 0;
   1.215 +
   1.216 +			/* check parity */
   1.217 +			/*if((parity & 1) == (valp & 1)) {}*/
   1.218 +			keybuf[key_wr] = (unsigned char)value;
   1.219 +			key_wr = NEXT_IDX(key_wr);
   1.220 +
   1.221 +			value = 0;
   1.222 +			parity = 0;
   1.223 +		}
   1.224 +	}
   1.225 +}