a500kbd

diff src/ps2kbd.c @ 3:31a1f0b53d98

- 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
line diff
     1.1 --- a/src/ps2kbd.c	Tue Oct 17 15:25:33 2017 +0300
     1.2 +++ b/src/ps2kbd.c	Wed Oct 18 08:20:58 2017 +0300
     1.3 @@ -3,6 +3,9 @@
     1.4  #include <util/delay.h>
     1.5  #include "ps2kbd.h"
     1.6  #include "defs.h"
     1.7 +#include "timer.h"
     1.8 +
     1.9 +#define TIMEOUT	100
    1.10  
    1.11  #define BUF_SZ	16
    1.12  #define BUF_IDX_MASK	(BUF_SZ - 1)
    1.13 @@ -10,34 +13,66 @@
    1.14  static volatile unsigned char keybuf[BUF_SZ];
    1.15  static volatile unsigned char key_rd, key_wr;
    1.16  
    1.17 -static volatile int sending;
    1.18 +static volatile int send_nbits, wait_ack;
    1.19 +static volatile unsigned char send_val, send_par;
    1.20  
    1.21 -void ps2write(unsigned char c)
    1.22 +static void abort_send(void);
    1.23 +
    1.24 +int ps2write(unsigned char c)
    1.25  {
    1.26 -#if 0
    1.27 -	int i;
    1.28 -	unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8);
    1.29 +	cli();
    1.30 +	send_nbits = 10;
    1.31 +	send_val = c;
    1.32 +	send_par = 0;	/* init to 0, will be calculated while sending */
    1.33  
    1.34 -	/* pull clock low for >60us */
    1.35 -	PS2LOW(BIT_CLK);
    1.36 -	_delay_us(60);
    1.37 +	/* inhibit transmission, hold at least 100us */
    1.38 +	PORTD &= ~PCLK_BIT;
    1.39 +	DDRD |= PCLK_BIT;
    1.40 +	EIFR |= (1 << INTF0);	/* clear pending interrupt due to clock transition */
    1.41 +	sei();
    1.42 +	_delay_us(100);
    1.43  
    1.44 -	/* then pull data low and release clock */
    1.45 -	PS2LOW(BIT_DATA);
    1.46 -	PS2REL(BIT_CLK);
    1.47 +	/* RTS by data low & release clock (this counts as start bit?) */
    1.48 +	PORTD &= ~PDATA_BIT;
    1.49 +	DDRD |= PDATA_BIT;
    1.50 +	DDRD &= ~PCLK_BIT;
    1.51  
    1.52 -	for(i=0; i<9; i++) {
    1.53 -		while(PINB & BIT_CLK);	/* wait for kbd to drive the clock low */
    1.54 -		PORTB |= out & 1;
    1.55 -		out >>= 1;
    1.56 -		while(!(PINB & BIT_CLK));	/* wait for kbd to drive the clock high */
    1.57 +	reset_timer();
    1.58 +	while(send_nbits > 0) {
    1.59 +		if(get_msec() > TIMEOUT) {
    1.60 +			abort_send();
    1.61 +			return -1;
    1.62 +		}
    1.63  	}
    1.64 +	_delay_us(5);
    1.65  
    1.66 -	PS2REL(BIT_DATA);
    1.67 -	/* wait for ack */
    1.68 -	while(PINB & BIT_DATA);
    1.69 -	while(!(PINB & BIT_DATA));
    1.70 -#endif
    1.71 +	/* release data line and wait for ack */
    1.72 +	cli();
    1.73 +	wait_ack = 1;
    1.74 +	sei();
    1.75 +	DDRD &= ~PDATA_BIT;
    1.76 +	reset_timer();
    1.77 +	while(wait_ack) {
    1.78 +		if(get_msec() > TIMEOUT) {
    1.79 +			abort_send();
    1.80 +			return -1;
    1.81 +		}
    1.82 +	}
    1.83 +	return 0;
    1.84 +}
    1.85 +
    1.86 +static void abort_send(void)
    1.87 +{
    1.88 +	cli();
    1.89 +	send_nbits = 0;
    1.90 +	wait_ack = 0;
    1.91 +	/* hold clock low for 100us */
    1.92 +	PORTD &= ~PCLK_BIT;
    1.93 +	DDRD |= PCLK_BIT;
    1.94 +	_delay_us(100);
    1.95 +	DDRD &= ~(PCLK_BIT | PDATA_BIT);
    1.96 +	EIFR |= (1 << INTF0);	/* clear pending interrupt */
    1.97 +	sei();
    1.98  }
    1.99  
   1.100  unsigned char ps2read(void)
   1.101 @@ -60,13 +95,80 @@
   1.102  	return key_rd != key_wr;
   1.103  }
   1.104  
   1.105 +int ps2wait(unsigned int timeout)
   1.106 +{
   1.107 +	reset_timer();
   1.108 +	while(key_rd == key_wr) {
   1.109 +		if(get_msec() >= timeout) return -1;
   1.110 +	}
   1.111 +	return 0;
   1.112 +}
   1.113 +
   1.114 +#define PS2_ACK		0xfa
   1.115 +#define PS2_RESEND	0xfe
   1.116 +#define PS2_ECHO	0xee
   1.117 +
   1.118 +int ps2setled(unsigned char state)
   1.119 +{
   1.120 +	unsigned char c;
   1.121 +
   1.122 +	ps2write(0xed);
   1.123 +	reset_timer();
   1.124 +	while(!ps2pending()) {
   1.125 +		if(get_msec() >= TIMEOUT) return -1;
   1.126 +	}
   1.127 +	c = ps2read();
   1.128 +	/*printf("ps2setled 1st response: %x\r\n", (unsigned int)c);*/
   1.129 +	if(c != PS2_ACK) return -1;
   1.130 +
   1.131 +	ps2write(state);
   1.132 +	reset_timer();
   1.133 +	while(!ps2pending()) {
   1.134 +		if(get_msec() >= TIMEOUT) return -1;
   1.135 +	}
   1.136 +	c = ps2read();
   1.137 +	/*printf("ps2setled 2nd response: %x\r\n", (unsigned int)c);*/
   1.138 +	if(c != PS2_ACK) return -1;
   1.139 +
   1.140 +	return 0;
   1.141 +}
   1.142 +
   1.143  ISR(INT0_vect)
   1.144  {
   1.145  	static unsigned char value, parity;
   1.146  	/*static unsigned char valp;*/
   1.147  	static int nbits;
   1.148  
   1.149 -	if(sending) {
   1.150 +	if(wait_ack) {
   1.151 +		if(!(PIND & PDATA_BIT)) {
   1.152 +			wait_ack = 0;
   1.153 +		}
   1.154 +		return;
   1.155 +	}
   1.156 +
   1.157 +	if(send_nbits > 0) {
   1.158 +		--send_nbits;
   1.159 +		switch(send_nbits) {
   1.160 +		case 1:		/* parity bit */
   1.161 +			if(send_par & 1) {	/* odd number of ones: parity 0 */
   1.162 +				PORTD &= ~PDATA_BIT;
   1.163 +			} else {	/* even number of ones: parity 1 */
   1.164 +				PORTD |= PDATA_BIT;
   1.165 +			}
   1.166 +			break;
   1.167 +		case 0:	/* stop bit: 1 */
   1.168 +			PORTD |= PDATA_BIT;
   1.169 +			break;
   1.170 +		default:
   1.171 +			if(send_val & 1) {
   1.172 +				PORTD |= PDATA_BIT;
   1.173 +				++send_par;
   1.174 +			} else {
   1.175 +				PORTD &= ~PDATA_BIT;
   1.176 +			}
   1.177 +			send_val >>= 1;
   1.178 +		}
   1.179 +
   1.180  	} else {
   1.181  		if(nbits > 0 && nbits < 9) {
   1.182  			value >>= 1;