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;