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