a500kbd

changeset 3:31a1f0b53d98 tip

- scroll lock now acts as caps lock - the scroll-lock light indicates drive activity
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 18 Oct 2017 08:20:58 +0300
parents a4fd9c5a6655
children
files src/amigakb.c src/main.c src/ps2kbd.c src/ps2kbd.h src/scantbl.h
diffstat 5 files changed, 173 insertions(+), 34 deletions(-) [+]
line diff
     1.1 --- a/src/amigakb.c	Tue Oct 17 15:25:33 2017 +0300
     1.2 +++ b/src/amigakb.c	Wed Oct 18 08:20:58 2017 +0300
     1.3 @@ -14,6 +14,17 @@
     1.4  {
     1.5  	int i;
     1.6  	static unsigned char prev_keycode = 0xff;
     1.7 +	static unsigned char capslk;
     1.8 +
     1.9 +	if(keycode == 0x62) {
    1.10 +		/* caps lock doesn't get a key release event when the key is released
    1.11 +		 * but rather when the caps lock is toggled off again
    1.12 +		 */
    1.13 +		if(!press) return;
    1.14 +
    1.15 +		capslk = ~capslk;
    1.16 +		press = capslk;
    1.17 +	}
    1.18  
    1.19  	/* keycode bit transfer order: 6 5 4 3 2 1 0 7 (7 is pressed flag) */
    1.20  	keycode = (keycode << 1) | (~press & 1);
     2.1 --- a/src/main.c	Tue Oct 17 15:25:33 2017 +0300
     2.2 +++ b/src/main.c	Wed Oct 18 08:20:58 2017 +0300
     2.3 @@ -22,10 +22,12 @@
     2.4  #define KF_TRANSIENT	0x0f
     2.5  #define KF_STICKY		0xf0
     2.6  
     2.7 +static unsigned char led_state;
     2.8 +
     2.9  int main(void)
    2.10  {
    2.11  	unsigned int keyflags = 0;
    2.12 -	unsigned char keycode;
    2.13 +	unsigned char c, keycode, prev_drvled = 0;
    2.14  	int press;
    2.15  
    2.16  	/* disable all pullups globally */
    2.17 @@ -46,8 +48,23 @@
    2.18  
    2.19  	EIMSK = (1 << INT0) | (1 << INT1);	/* enable ps/2 clock interrupt */
    2.20  
    2.21 +	ps2setled(0);	/* start with all LEDs off */
    2.22 +
    2.23  	for(;;) {
    2.24 -		unsigned char c = ps2read();
    2.25 +		while(!ps2pending()) {
    2.26 +			unsigned char drvled = PIND & ADRVLED_BIT;
    2.27 +			if(drvled != prev_drvled) {
    2.28 +				prev_drvled = drvled;
    2.29 +				if(drvled) {
    2.30 +					led_state |= PS2LED_SCRLK;
    2.31 +				} else {
    2.32 +					led_state &= ~PS2LED_SCRLK;
    2.33 +				}
    2.34 +				ps2setled(led_state);
    2.35 +			}
    2.36 +		}
    2.37 +
    2.38 +		c = ps2read();
    2.39  		switch(c) {
    2.40  		case 0xe0:	/* extended */
    2.41  			keyflags |= KF_EXT;
    2.42 @@ -66,12 +83,10 @@
    2.43  
    2.44  			keycode = 0xff;
    2.45  			if(keyflags & KF_EXT) {
    2.46 -				printf("ext ");
    2.47  				if(c < KEYMAP_EXT_SIZE) {
    2.48  					keycode = keymap_ext[(int)c];
    2.49  				}
    2.50  			} else if(keyflags & KF_EXT1) {
    2.51 -				printf("ext1 ");
    2.52  			} else {
    2.53  				if(c < KEYMAP_NORMAL_SIZE) {
    2.54  					keycode = keymap_normal[(int)c];
    2.55 @@ -109,17 +124,19 @@
    2.56  				amikb_reset();
    2.57  			}
    2.58  
    2.59 -			printf("scancode %x -> ", (unsigned int)c);
    2.60  			if(keycode != 0xff) {
    2.61 -				amikb_sendkey(keycode, ~keyflags & KF_BRK);
    2.62 -				printf("[%s] amiga key %xh\r\n", press ? "press" : "release", keycode);
    2.63 +				int press = ~keyflags & KF_BRK;
    2.64 +				amikb_sendkey(keycode, press);
    2.65 +				if(keycode == 0x62 && press) {
    2.66 +					led_state ^= PS2LED_CAPSLK;
    2.67 +					ps2setled(led_state);
    2.68 +				}
    2.69 +				/*printf("scancode %x -> [%s] amiga key %xh\r\n", (unsigned int)c, press ? "press" : "release", keycode);*/
    2.70  			} else {
    2.71 -				printf("[%s] no translation\r\n", press ? "press" : "release");
    2.72 +				printf("PS/2 unknown command or keycode: %x\r\n", (unsigned int)c);
    2.73  			}
    2.74  			keyflags &= ~KF_TRANSIENT;
    2.75  		}
    2.76  	}
    2.77  	return 0;
    2.78  }
    2.79 -
    2.80 -
     3.1 --- a/src/ps2kbd.c	Tue Oct 17 15:25:33 2017 +0300
     3.2 +++ b/src/ps2kbd.c	Wed Oct 18 08:20:58 2017 +0300
     3.3 @@ -3,6 +3,9 @@
     3.4  #include <util/delay.h>
     3.5  #include "ps2kbd.h"
     3.6  #include "defs.h"
     3.7 +#include "timer.h"
     3.8 +
     3.9 +#define TIMEOUT	100
    3.10  
    3.11  #define BUF_SZ	16
    3.12  #define BUF_IDX_MASK	(BUF_SZ - 1)
    3.13 @@ -10,34 +13,66 @@
    3.14  static volatile unsigned char keybuf[BUF_SZ];
    3.15  static volatile unsigned char key_rd, key_wr;
    3.16  
    3.17 -static volatile int sending;
    3.18 +static volatile int send_nbits, wait_ack;
    3.19 +static volatile unsigned char send_val, send_par;
    3.20  
    3.21 -void ps2write(unsigned char c)
    3.22 +static void abort_send(void);
    3.23 +
    3.24 +int ps2write(unsigned char c)
    3.25  {
    3.26 -#if 0
    3.27 -	int i;
    3.28 -	unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8);
    3.29 +	cli();
    3.30 +	send_nbits = 10;
    3.31 +	send_val = c;
    3.32 +	send_par = 0;	/* init to 0, will be calculated while sending */
    3.33  
    3.34 -	/* pull clock low for >60us */
    3.35 -	PS2LOW(BIT_CLK);
    3.36 -	_delay_us(60);
    3.37 +	/* inhibit transmission, hold at least 100us */
    3.38 +	PORTD &= ~PCLK_BIT;
    3.39 +	DDRD |= PCLK_BIT;
    3.40 +	EIFR |= (1 << INTF0);	/* clear pending interrupt due to clock transition */
    3.41 +	sei();
    3.42 +	_delay_us(100);
    3.43  
    3.44 -	/* then pull data low and release clock */
    3.45 -	PS2LOW(BIT_DATA);
    3.46 -	PS2REL(BIT_CLK);
    3.47 +	/* RTS by data low & release clock (this counts as start bit?) */
    3.48 +	PORTD &= ~PDATA_BIT;
    3.49 +	DDRD |= PDATA_BIT;
    3.50 +	DDRD &= ~PCLK_BIT;
    3.51  
    3.52 -	for(i=0; i<9; i++) {
    3.53 -		while(PINB & BIT_CLK);	/* wait for kbd to drive the clock low */
    3.54 -		PORTB |= out & 1;
    3.55 -		out >>= 1;
    3.56 -		while(!(PINB & BIT_CLK));	/* wait for kbd to drive the clock high */
    3.57 +	reset_timer();
    3.58 +	while(send_nbits > 0) {
    3.59 +		if(get_msec() > TIMEOUT) {
    3.60 +			abort_send();
    3.61 +			return -1;
    3.62 +		}
    3.63  	}
    3.64 +	_delay_us(5);
    3.65  
    3.66 -	PS2REL(BIT_DATA);
    3.67 -	/* wait for ack */
    3.68 -	while(PINB & BIT_DATA);
    3.69 -	while(!(PINB & BIT_DATA));
    3.70 -#endif
    3.71 +	/* release data line and wait for ack */
    3.72 +	cli();
    3.73 +	wait_ack = 1;
    3.74 +	sei();
    3.75 +	DDRD &= ~PDATA_BIT;
    3.76 +	reset_timer();
    3.77 +	while(wait_ack) {
    3.78 +		if(get_msec() > TIMEOUT) {
    3.79 +			abort_send();
    3.80 +			return -1;
    3.81 +		}
    3.82 +	}
    3.83 +	return 0;
    3.84 +}
    3.85 +
    3.86 +static void abort_send(void)
    3.87 +{
    3.88 +	cli();
    3.89 +	send_nbits = 0;
    3.90 +	wait_ack = 0;
    3.91 +	/* hold clock low for 100us */
    3.92 +	PORTD &= ~PCLK_BIT;
    3.93 +	DDRD |= PCLK_BIT;
    3.94 +	_delay_us(100);
    3.95 +	DDRD &= ~(PCLK_BIT | PDATA_BIT);
    3.96 +	EIFR |= (1 << INTF0);	/* clear pending interrupt */
    3.97 +	sei();
    3.98  }
    3.99  
   3.100  unsigned char ps2read(void)
   3.101 @@ -60,13 +95,80 @@
   3.102  	return key_rd != key_wr;
   3.103  }
   3.104  
   3.105 +int ps2wait(unsigned int timeout)
   3.106 +{
   3.107 +	reset_timer();
   3.108 +	while(key_rd == key_wr) {
   3.109 +		if(get_msec() >= timeout) return -1;
   3.110 +	}
   3.111 +	return 0;
   3.112 +}
   3.113 +
   3.114 +#define PS2_ACK		0xfa
   3.115 +#define PS2_RESEND	0xfe
   3.116 +#define PS2_ECHO	0xee
   3.117 +
   3.118 +int ps2setled(unsigned char state)
   3.119 +{
   3.120 +	unsigned char c;
   3.121 +
   3.122 +	ps2write(0xed);
   3.123 +	reset_timer();
   3.124 +	while(!ps2pending()) {
   3.125 +		if(get_msec() >= TIMEOUT) return -1;
   3.126 +	}
   3.127 +	c = ps2read();
   3.128 +	/*printf("ps2setled 1st response: %x\r\n", (unsigned int)c);*/
   3.129 +	if(c != PS2_ACK) return -1;
   3.130 +
   3.131 +	ps2write(state);
   3.132 +	reset_timer();
   3.133 +	while(!ps2pending()) {
   3.134 +		if(get_msec() >= TIMEOUT) return -1;
   3.135 +	}
   3.136 +	c = ps2read();
   3.137 +	/*printf("ps2setled 2nd response: %x\r\n", (unsigned int)c);*/
   3.138 +	if(c != PS2_ACK) return -1;
   3.139 +
   3.140 +	return 0;
   3.141 +}
   3.142 +
   3.143  ISR(INT0_vect)
   3.144  {
   3.145  	static unsigned char value, parity;
   3.146  	/*static unsigned char valp;*/
   3.147  	static int nbits;
   3.148  
   3.149 -	if(sending) {
   3.150 +	if(wait_ack) {
   3.151 +		if(!(PIND & PDATA_BIT)) {
   3.152 +			wait_ack = 0;
   3.153 +		}
   3.154 +		return;
   3.155 +	}
   3.156 +
   3.157 +	if(send_nbits > 0) {
   3.158 +		--send_nbits;
   3.159 +		switch(send_nbits) {
   3.160 +		case 1:		/* parity bit */
   3.161 +			if(send_par & 1) {	/* odd number of ones: parity 0 */
   3.162 +				PORTD &= ~PDATA_BIT;
   3.163 +			} else {	/* even number of ones: parity 1 */
   3.164 +				PORTD |= PDATA_BIT;
   3.165 +			}
   3.166 +			break;
   3.167 +		case 0:	/* stop bit: 1 */
   3.168 +			PORTD |= PDATA_BIT;
   3.169 +			break;
   3.170 +		default:
   3.171 +			if(send_val & 1) {
   3.172 +				PORTD |= PDATA_BIT;
   3.173 +				++send_par;
   3.174 +			} else {
   3.175 +				PORTD &= ~PDATA_BIT;
   3.176 +			}
   3.177 +			send_val >>= 1;
   3.178 +		}
   3.179 +
   3.180  	} else {
   3.181  		if(nbits > 0 && nbits < 9) {
   3.182  			value >>= 1;
     4.1 --- a/src/ps2kbd.h	Tue Oct 17 15:25:33 2017 +0300
     4.2 +++ b/src/ps2kbd.h	Wed Oct 18 08:20:58 2017 +0300
     4.3 @@ -1,8 +1,17 @@
     4.4  #ifndef PS2KBD_H_
     4.5  #define PS2KBD_H_
     4.6  
     4.7 -void ps2write(unsigned char c);
     4.8 +enum {
     4.9 +	PS2LED_SCRLK = 1,
    4.10 +	PS2LED_NUMLK = 2,
    4.11 +	PS2LED_CAPSLK = 4
    4.12 +};
    4.13 +
    4.14 +int ps2write(unsigned char c);
    4.15  unsigned char ps2read(void);
    4.16  int ps2pending(void);
    4.17 +int ps2wait(unsigned int timeout);
    4.18 +
    4.19 +int ps2setled(unsigned char state);
    4.20  
    4.21  #endif	/* PS2KBD_H_ */
     5.1 --- a/src/scantbl.h	Tue Oct 17 15:25:33 2017 +0300
     5.2 +++ b/src/scantbl.h	Wed Oct 18 08:20:58 2017 +0300
     5.3 @@ -76,7 +76,7 @@
     5.4  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff,		/* 60 - 67: - - - - - - backsp - */
     5.5  	0xff, 0x1d, 0xff, 0x2d, 0x3d, 0xff, 0xff, 0xff,		/* 68 - 6f: - KP1 - KP4 KP7 - - - */
     5.6  	0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x45, 0x5a,		/* 70 - 77: KP0 KP. KP2 KP5 KP6 KP8 esc numlk */
     5.7 -	0xff, 0x5e, 0x1f, 0x4a, 0x5d, 0x3f, 0x5b, 0xff,		/* 78 - 7f: f11 KP+ KP3 KP- KP* KP9 scrlk - */
     5.8 +	0xff, 0x5e, 0x1f, 0x4a, 0x5d, 0x3f, 0x62, 0xff,		/* 78 - 7f: f11 KP+ KP3 KP- KP* KP9 scrlk(capslock) - */
     5.9  	0xff, 0xff, 0xff, 0x56								/* 80 - 83: - - - f7 */
    5.10  };
    5.11