# HG changeset patch # User John Tsiombikas # Date 1508304058 -10800 # Node ID 31a1f0b53d984763d16c6c715b8a13045649ad7b # Parent a4fd9c5a665547e2d20cd7eab05b9a61b1d91696 - scroll lock now acts as caps lock - the scroll-lock light indicates drive activity diff -r a4fd9c5a6655 -r 31a1f0b53d98 src/amigakb.c --- a/src/amigakb.c Tue Oct 17 15:25:33 2017 +0300 +++ b/src/amigakb.c Wed Oct 18 08:20:58 2017 +0300 @@ -14,6 +14,17 @@ { int i; static unsigned char prev_keycode = 0xff; + static unsigned char capslk; + + if(keycode == 0x62) { + /* caps lock doesn't get a key release event when the key is released + * but rather when the caps lock is toggled off again + */ + if(!press) return; + + capslk = ~capslk; + press = capslk; + } /* keycode bit transfer order: 6 5 4 3 2 1 0 7 (7 is pressed flag) */ keycode = (keycode << 1) | (~press & 1); diff -r a4fd9c5a6655 -r 31a1f0b53d98 src/main.c --- a/src/main.c Tue Oct 17 15:25:33 2017 +0300 +++ b/src/main.c Wed Oct 18 08:20:58 2017 +0300 @@ -22,10 +22,12 @@ #define KF_TRANSIENT 0x0f #define KF_STICKY 0xf0 +static unsigned char led_state; + int main(void) { unsigned int keyflags = 0; - unsigned char keycode; + unsigned char c, keycode, prev_drvled = 0; int press; /* disable all pullups globally */ @@ -46,8 +48,23 @@ EIMSK = (1 << INT0) | (1 << INT1); /* enable ps/2 clock interrupt */ + ps2setled(0); /* start with all LEDs off */ + for(;;) { - unsigned char c = ps2read(); + while(!ps2pending()) { + unsigned char drvled = PIND & ADRVLED_BIT; + if(drvled != prev_drvled) { + prev_drvled = drvled; + if(drvled) { + led_state |= PS2LED_SCRLK; + } else { + led_state &= ~PS2LED_SCRLK; + } + ps2setled(led_state); + } + } + + c = ps2read(); switch(c) { case 0xe0: /* extended */ keyflags |= KF_EXT; @@ -66,12 +83,10 @@ keycode = 0xff; if(keyflags & KF_EXT) { - printf("ext "); if(c < KEYMAP_EXT_SIZE) { keycode = keymap_ext[(int)c]; } } else if(keyflags & KF_EXT1) { - printf("ext1 "); } else { if(c < KEYMAP_NORMAL_SIZE) { keycode = keymap_normal[(int)c]; @@ -109,17 +124,19 @@ amikb_reset(); } - printf("scancode %x -> ", (unsigned int)c); if(keycode != 0xff) { - amikb_sendkey(keycode, ~keyflags & KF_BRK); - printf("[%s] amiga key %xh\r\n", press ? "press" : "release", keycode); + int press = ~keyflags & KF_BRK; + amikb_sendkey(keycode, press); + if(keycode == 0x62 && press) { + led_state ^= PS2LED_CAPSLK; + ps2setled(led_state); + } + /*printf("scancode %x -> [%s] amiga key %xh\r\n", (unsigned int)c, press ? "press" : "release", keycode);*/ } else { - printf("[%s] no translation\r\n", press ? "press" : "release"); + printf("PS/2 unknown command or keycode: %x\r\n", (unsigned int)c); } keyflags &= ~KF_TRANSIENT; } } return 0; } - - diff -r a4fd9c5a6655 -r 31a1f0b53d98 src/ps2kbd.c --- a/src/ps2kbd.c Tue Oct 17 15:25:33 2017 +0300 +++ b/src/ps2kbd.c Wed Oct 18 08:20:58 2017 +0300 @@ -3,6 +3,9 @@ #include #include "ps2kbd.h" #include "defs.h" +#include "timer.h" + +#define TIMEOUT 100 #define BUF_SZ 16 #define BUF_IDX_MASK (BUF_SZ - 1) @@ -10,34 +13,66 @@ static volatile unsigned char keybuf[BUF_SZ]; static volatile unsigned char key_rd, key_wr; -static volatile int sending; +static volatile int send_nbits, wait_ack; +static volatile unsigned char send_val, send_par; -void ps2write(unsigned char c) +static void abort_send(void); + +int ps2write(unsigned char c) { -#if 0 - int i; - unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8); + cli(); + send_nbits = 10; + send_val = c; + send_par = 0; /* init to 0, will be calculated while sending */ - /* pull clock low for >60us */ - PS2LOW(BIT_CLK); - _delay_us(60); + /* inhibit transmission, hold at least 100us */ + PORTD &= ~PCLK_BIT; + DDRD |= PCLK_BIT; + EIFR |= (1 << INTF0); /* clear pending interrupt due to clock transition */ + sei(); + _delay_us(100); - /* then pull data low and release clock */ - PS2LOW(BIT_DATA); - PS2REL(BIT_CLK); + /* RTS by data low & release clock (this counts as start bit?) */ + PORTD &= ~PDATA_BIT; + DDRD |= PDATA_BIT; + DDRD &= ~PCLK_BIT; - for(i=0; i<9; i++) { - while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */ - PORTB |= out & 1; - out >>= 1; - while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */ + reset_timer(); + while(send_nbits > 0) { + if(get_msec() > TIMEOUT) { + abort_send(); + return -1; + } } + _delay_us(5); - PS2REL(BIT_DATA); - /* wait for ack */ - while(PINB & BIT_DATA); - while(!(PINB & BIT_DATA)); -#endif + /* release data line and wait for ack */ + cli(); + wait_ack = 1; + sei(); + DDRD &= ~PDATA_BIT; + reset_timer(); + while(wait_ack) { + if(get_msec() > TIMEOUT) { + abort_send(); + return -1; + } + } + return 0; +} + +static void abort_send(void) +{ + cli(); + send_nbits = 0; + wait_ack = 0; + /* hold clock low for 100us */ + PORTD &= ~PCLK_BIT; + DDRD |= PCLK_BIT; + _delay_us(100); + DDRD &= ~(PCLK_BIT | PDATA_BIT); + EIFR |= (1 << INTF0); /* clear pending interrupt */ + sei(); } unsigned char ps2read(void) @@ -60,13 +95,80 @@ return key_rd != key_wr; } +int ps2wait(unsigned int timeout) +{ + reset_timer(); + while(key_rd == key_wr) { + if(get_msec() >= timeout) return -1; + } + return 0; +} + +#define PS2_ACK 0xfa +#define PS2_RESEND 0xfe +#define PS2_ECHO 0xee + +int ps2setled(unsigned char state) +{ + unsigned char c; + + ps2write(0xed); + reset_timer(); + while(!ps2pending()) { + if(get_msec() >= TIMEOUT) return -1; + } + c = ps2read(); + /*printf("ps2setled 1st response: %x\r\n", (unsigned int)c);*/ + if(c != PS2_ACK) return -1; + + ps2write(state); + reset_timer(); + while(!ps2pending()) { + if(get_msec() >= TIMEOUT) return -1; + } + c = ps2read(); + /*printf("ps2setled 2nd response: %x\r\n", (unsigned int)c);*/ + if(c != PS2_ACK) return -1; + + return 0; +} + ISR(INT0_vect) { static unsigned char value, parity; /*static unsigned char valp;*/ static int nbits; - if(sending) { + if(wait_ack) { + if(!(PIND & PDATA_BIT)) { + wait_ack = 0; + } + return; + } + + if(send_nbits > 0) { + --send_nbits; + switch(send_nbits) { + case 1: /* parity bit */ + if(send_par & 1) { /* odd number of ones: parity 0 */ + PORTD &= ~PDATA_BIT; + } else { /* even number of ones: parity 1 */ + PORTD |= PDATA_BIT; + } + break; + case 0: /* stop bit: 1 */ + PORTD |= PDATA_BIT; + break; + default: + if(send_val & 1) { + PORTD |= PDATA_BIT; + ++send_par; + } else { + PORTD &= ~PDATA_BIT; + } + send_val >>= 1; + } + } else { if(nbits > 0 && nbits < 9) { value >>= 1; diff -r a4fd9c5a6655 -r 31a1f0b53d98 src/ps2kbd.h --- a/src/ps2kbd.h Tue Oct 17 15:25:33 2017 +0300 +++ b/src/ps2kbd.h Wed Oct 18 08:20:58 2017 +0300 @@ -1,8 +1,17 @@ #ifndef PS2KBD_H_ #define PS2KBD_H_ -void ps2write(unsigned char c); +enum { + PS2LED_SCRLK = 1, + PS2LED_NUMLK = 2, + PS2LED_CAPSLK = 4 +}; + +int ps2write(unsigned char c); unsigned char ps2read(void); int ps2pending(void); +int ps2wait(unsigned int timeout); + +int ps2setled(unsigned char state); #endif /* PS2KBD_H_ */ diff -r a4fd9c5a6655 -r 31a1f0b53d98 src/scantbl.h --- a/src/scantbl.h Tue Oct 17 15:25:33 2017 +0300 +++ b/src/scantbl.h Wed Oct 18 08:20:58 2017 +0300 @@ -76,7 +76,7 @@ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, /* 60 - 67: - - - - - - backsp - */ 0xff, 0x1d, 0xff, 0x2d, 0x3d, 0xff, 0xff, 0xff, /* 68 - 6f: - KP1 - KP4 KP7 - - - */ 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x45, 0x5a, /* 70 - 77: KP0 KP. KP2 KP5 KP6 KP8 esc numlk */ - 0xff, 0x5e, 0x1f, 0x4a, 0x5d, 0x3f, 0x5b, 0xff, /* 78 - 7f: f11 KP+ KP3 KP- KP* KP9 scrlk - */ + 0xff, 0x5e, 0x1f, 0x4a, 0x5d, 0x3f, 0x62, 0xff, /* 78 - 7f: f11 KP+ KP3 KP- KP* KP9 scrlk(capslock) - */ 0xff, 0xff, 0xff, 0x56 /* 80 - 83: - - - f7 */ };