neuttower/kbd.c

95 lines
1.8 KiB
C
Executable file

#include <stdio.h>
#include <dos.h>
#include "kbd.h"
static void interrupt (*oldKbdISR)() = NULL;
void kbd_cleanup() {
if (oldKbdISR != NULL) {
setvect(KBD_INT, oldKbdISR);
oldKbdISR = NULL;
}
}
volatile unsigned char keybuf[128] = { 0 };
volatile char kbd_triggered = 0;
static void interrupt kbd_isr() {
unsigned char raw;
char ctl;
disable();
raw = inp(0x60);
ctl = inp(0x61) | 0x82;
outp(0x61, ctl);
outp(0x61, ctl & 0x7f);
if (raw & 0x80) {
keybuf[raw & 0x7f] &= ~KEY_SIGNAL;
} else {
keybuf[raw] |= KEY_SIGNAL;
}
kbd_triggered = raw;
outp(0x20, 0x20);
enable();
}
unsigned char kbd_wait_raw() {
kbd_triggered = 0;
while (!kbd_triggered) {}
return kbd_triggered;
}
static unsigned char kbd_any() {
unsigned char key;
kbd_debounce();
for (key = 0; key < 128; key ++) {
if (keybuf[key] != KEY_OFF) {
return key;
}
}
return 0xff;
}
unsigned char kbd_wait() {
unsigned char found = kbd_any();
for (; found != 0xff; found = kbd_any()) {}
for (; found == 0xff; found = kbd_any()) {}
return found;
}
void kbd_init() {
if (oldKbdISR == NULL) {
memset(keybuf, 0, 128);
oldKbdISR = getvect(KBD_INT);
setvect(KBD_INT, kbd_isr);
atexit(kbd_cleanup);
}
}
void kbd_debounce() {
int i = 0;
disable();
for (i = 0; i < 128; i ++) {
unsigned char signal = keybuf[i] & KEY_SIGNAL;
unsigned char keystate = keybuf[i] & 0x0f;
if (!signal) {
if (keystate == KEY_RELEASED) {
keystate = KEY_OFF;
} else if (keystate != KEY_OFF) {
keystate = KEY_RELEASED;
}
} else {
if (keystate == KEY_OFF) {
keystate = KEY_PRESSED;
} else if (keystate == KEY_PRESSED) {
keystate = KEY_DOWN;
}
}
keybuf[i] = signal | keystate;
}
enable();
}