URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
[/] [eco32/] [trunk/] [sim/] [dspkbd.c] - Rev 182
Go to most recent revision | Compare with Previous | Blame | View Log
/* * dspkbd.h -- display & keyboard controller simulation */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <setjmp.h> #include "common.h" #include "console.h" #include "error.h" #include "except.h" #include "cpu.h" #include "timer.h" #include "dspkbd.h" static Bool debug = false; static Bool debugKeycode = false; static volatile Bool installed = false; static void blinkScreen(void); static void keyPressed(unsigned int xKeycode); static void keyReleased(unsigned int xKeycode); /**************************************************************/ /**************************************************************/ /* common definitions, global variables */ #include <pthread.h> #include <unistd.h> #include <time.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #define WINDOW_SIZE_X 640 #define WINDOW_SIZE_Y 480 #define WINDOW_POS_X 100 #define WINDOW_POS_Y 100 #define C2B(c,ch) (((((c) & 0xFF) * ch.scale) >> 8) * ch.factor) #define RGB2PIXEL(r,g,b) (C2B(r, vga.red) | \ C2B(g, vga.green) | \ C2B(b, vga.blue)) typedef struct { unsigned long scale; unsigned long factor; } ColorChannel; typedef struct { int argc; char **argv; Display *display; Window win; GC gc; XImage *image; ColorChannel red, green, blue; XExposeEvent expose; XClientMessageEvent shutdown; } VGA; static VGA vga; /**************************************************************/ /* monitor server */ static ColorChannel mask2channel(unsigned long mask) { unsigned long f; ColorChannel ch; if (mask == 0) { error("color mask is 0 in mask2channel"); } for (f = 1; (mask & 1) == 0; f <<= 1) { mask >>= 1; } ch.factor = f; ch.scale = mask + 1; while ((mask & 1) != 0) { mask >>= 1; } if (mask != 0) { error("scattered color mask bits in mask2channel"); } return ch; } static void initMonitor(int argc, char *argv[]) { int screenNum; Window rootWin; XVisualInfo visualTemp; XVisualInfo *visualInfo; int visualCount; int bestMatch; int bestDepth; Visual *visual; int i; unsigned long pixel; int x, y; Colormap colormap; XSetWindowAttributes attrib; XSizeHints *sizeHints; XWMHints *wmHints; XClassHint *classHints; XTextProperty windowName; XGCValues gcValues; /* connect to X server */ if (XInitThreads() == 0) { error("no thread support for X11"); } vga.display = XOpenDisplay(NULL); if (vga.display == NULL) { error("cannot connect to X server"); } screenNum = DefaultScreen(vga.display); rootWin = RootWindow(vga.display, screenNum); /* find TrueColor visual */ visualTemp.screen = screenNum; visualTemp.class = TrueColor; visualInfo = XGetVisualInfo(vga.display, VisualClassMask | VisualScreenMask, &visualTemp, &visualCount); if (visualInfo == NULL || visualCount == 0) { error("no TrueColor visual found"); } bestMatch = 0; bestDepth = visualInfo[0].depth; visual = visualInfo[0].visual; for (i = 1; i < visualCount; i++) { if (visualInfo[i].depth > bestDepth) { bestMatch = i; bestDepth = visualInfo[i].depth; visual = visualInfo[i].visual; } } /* build color channels */ vga.red = mask2channel(visualInfo[bestMatch].red_mask); vga.green = mask2channel(visualInfo[bestMatch].green_mask); vga.blue = mask2channel(visualInfo[bestMatch].blue_mask); /* create and initialize image */ vga.image = XCreateImage(vga.display, visual, bestDepth, ZPixmap, 0, NULL, WINDOW_SIZE_X, WINDOW_SIZE_Y, 32, 0); if (vga.image == NULL) { error("cannot allocate image"); } vga.image->data = malloc(vga.image->height * vga.image->bytes_per_line); if (vga.image->data == NULL) { error("cannot allocate image memory"); } pixel = RGB2PIXEL(0, 0, 0); for (y = 0; y < WINDOW_SIZE_Y; y++) { for (x = 0; x < WINDOW_SIZE_X; x++) { XPutPixel(vga.image, x, y, pixel); } } /* allocate a colormap */ colormap = XCreateColormap(vga.display, rootWin, visual, AllocNone); /* create the window */ attrib.colormap = colormap; attrib.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask; attrib.background_pixel = RGB2PIXEL(0, 0, 0); attrib.border_pixel = RGB2PIXEL(0, 0, 0); vga.win = XCreateWindow(vga.display, rootWin, WINDOW_POS_X, WINDOW_POS_Y, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0, bestDepth, InputOutput, visual, CWEventMask | CWColormap | CWBackPixel | CWBorderPixel, &attrib); /* give hints to window manager */ sizeHints = XAllocSizeHints(); wmHints = XAllocWMHints(); classHints = XAllocClassHint(); if (sizeHints == NULL || wmHints == NULL || classHints == NULL) { error("hint allocation failed"); } sizeHints->flags = PMinSize | PMaxSize; sizeHints->min_width = WINDOW_SIZE_X; sizeHints->min_height = WINDOW_SIZE_Y; sizeHints->max_width = WINDOW_SIZE_X; sizeHints->max_height = WINDOW_SIZE_Y; wmHints->flags = StateHint | InputHint; wmHints->input = True; wmHints->initial_state = NormalState; classHints->res_name = "ECO32 Console"; classHints->res_class = "ECO32"; if (XStringListToTextProperty(&classHints->res_name, 1, &windowName) == 0) { error("property allocation failed"); } XSetWMProperties(vga.display, vga.win, &windowName, NULL, argv, argc, sizeHints, wmHints, classHints); /* create a GC */ vga.gc = XCreateGC(vga.display, vga.win, 0, &gcValues); /* finally get the window displayed */ XMapWindow(vga.display, vga.win); /* prepare expose event */ vga.expose.type = Expose; vga.expose.display = vga.display; vga.expose.window = vga.win; vga.expose.x = 0; vga.expose.y = 0; vga.expose.width = WINDOW_SIZE_X; vga.expose.height = WINDOW_SIZE_Y; vga.expose.count = 0; /* prepare shutdown event */ vga.shutdown.type = ClientMessage; vga.shutdown.display = vga.display; vga.shutdown.window = vga.win; vga.shutdown.message_type = XA_WM_COMMAND; vga.shutdown.format = 32; vga.shutdown.data.l[0] = 0xDEADBEEF; /* say that the graphics controller is installed */ XSync(vga.display, False); installed = true; } static void exitMonitor(void) { XFreeGC(vga.display, vga.gc); XUnmapWindow(vga.display, vga.win); XDestroyWindow(vga.display, vga.win); XDestroyImage(vga.image); XCloseDisplay(vga.display); installed = false; } static int ioErrorHandler(Display *display) { error("connection to monitor window lost"); /* never reached */ return 0; } static void *server(void *ignore) { Bool run; XEvent event; initMonitor(vga.argc, vga.argv); XSetIOErrorHandler(ioErrorHandler); run = true; while (run) { XNextEvent(vga.display, &event); switch (event.type) { case Expose: blinkScreen(); XPutImage(vga.display, vga.win, vga.gc, vga.image, event.xexpose.x, event.xexpose.y, event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height); break; case ClientMessage: if (event.xclient.message_type == XA_WM_COMMAND && event.xclient.format == 32 && event.xclient.data.l[0] == 0xDEADBEEF) { run = false; } break; case KeyPress: keyPressed(event.xkey.keycode); break; case KeyRelease: keyReleased(event.xkey.keycode); break; default: break; } } exitMonitor(); return NULL; } /**************************************************************/ /* refresh timer */ static Bool refreshRunning = false; static Bool blink = false; static void *refresh(void *ignore) { static int blinkCounter = 0; struct timespec delay; while (refreshRunning) { if (++blinkCounter == 5) { blinkCounter = 0; blink = !blink; } XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.expose); XFlush(vga.display); delay.tv_sec = 0; delay.tv_nsec = 100 * 1000 * 1000; nanosleep(&delay, &delay); } return NULL; } /**************************************************************/ /* server interface */ static int myArgc = 1; static char *myArgv[] = { "eco32", NULL }; static void vgaInit(void) { pthread_attr_t attr; pthread_t thread; /* start monitor server in a separate thread */ vga.argc = myArgc; vga.argv = myArgv; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thread, &attr, server, NULL) != 0) { error("cannot start monitor server"); } while (!installed) sleep(1); /* start refresh timer in another thread */ refreshRunning = true; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thread, &attr, refresh, NULL) != 0) { error("cannot start refresh timer"); } } static void vgaExit(void) { refreshRunning = false; sleep(1); XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.shutdown); XSync(vga.display, False); while (installed) sleep(1); } static void vgaWrite(int x, int y, int r, int g, int b) { XPutPixel(vga.image, x, y, RGB2PIXEL(r, g, b)); } /**************************************************************/ /**************************************************************/ #define CELL_SIZE_X 8 #define CELL_SIZE_Y 16 #define TEXT_SIZE_X (WINDOW_SIZE_X / CELL_SIZE_X) #define TEXT_SIZE_Y (WINDOW_SIZE_Y / CELL_SIZE_Y) static Half text[TEXT_SIZE_Y][TEXT_SIZE_X]; static Byte font[] = { #include "font" }; static void updateCharacter(int x, int y, Half c) { int xx, yy; int i, j; Byte pixels; int r, g, b; xx = x * CELL_SIZE_X; yy = y * CELL_SIZE_Y; for (j = 0; j < CELL_SIZE_Y; j++) { pixels = font[(c & 0x00FF) * CELL_SIZE_Y + j]; for (i = 0; i < CELL_SIZE_X; i++) { if ((pixels & (1 << (CELL_SIZE_X - 1 - i))) != 0 && !((c & 0x8000) != 0 && blink)) { /* foreground */ if (c & 0x0800) { /* intensify bit is on */ r = (c & 0x0400) ? 255 : 73; g = (c & 0x0200) ? 255 : 73; b = (c & 0x0100) ? 255 : 73; } else { /* intensify bit is off */ r = (c & 0x0400) ? 146 : 0; g = (c & 0x0200) ? 146 : 0; b = (c & 0x0100) ? 146 : 0; } } else { /* background */ r = (c & 0x4000) ? 146 : 0; g = (c & 0x2000) ? 146 : 0; b = (c & 0x1000) ? 146 : 0; } vgaWrite(xx + i, yy + j, r, g, b); } } } static void blinkScreen(void) { static Bool previousBlink = false; int x, y; Half c; if (previousBlink == blink) { /* blink state didn't change, nothing to do */ return; } previousBlink = blink; for (y = 0; y < TEXT_SIZE_Y; y++) { for (x = 0; x < TEXT_SIZE_X; x++) { /* update the character if it is blinking */ c = text[y][x]; if (c & 0x8000) { updateCharacter(x, y, c); } } } } static Half readCharAndAttr(int x, int y) { return text[y][x]; } static void writeCharAndAttr(int x, int y, Half c) { text[y][x] = c; updateCharacter(x, y, c); } static char *screen[] = { #include "screen" }; static void loadSplashScreen(void) { int x, y; char *p; for (y = 0; y < TEXT_SIZE_Y; y++) { p = screen[y]; for (x = 0; x < TEXT_SIZE_X; x++) { writeCharAndAttr(x, y, (Half) 0x0700 | (Half) *p); p++; } } } /**************************************************************/ Word displayRead(Word addr) { int x, y; Word data; if (debug) { cPrintf("\n**** DISPLAY READ from 0x%08X", addr); } if (!installed) { throwException(EXC_BUS_TIMEOUT); } x = (addr >> 2) & ((1 << 7) - 1); y = (addr >> 9) & ((1 << 5) - 1); if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) { throwException(EXC_BUS_TIMEOUT); } data = readCharAndAttr(x, y); if (debug) { cPrintf(", data = 0x%08X ****\n", data); } return data; } void displayWrite(Word addr, Word data) { int x, y; if (debug) { cPrintf("\n**** DISPLAY WRITE to 0x%08X, data = 0x%08X ****\n", addr, data); } if (!installed) { throwException(EXC_BUS_TIMEOUT); } x = (addr >> 2) & ((1 << 7) - 1); y = (addr >> 9) & ((1 << 5) - 1); if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) { throwException(EXC_BUS_TIMEOUT); } writeCharAndAttr(x, y, data); } void displayReset(void) { if (!installed) { return; } cPrintf("Resetting Display...\n"); loadSplashScreen(); } void displayInit(void) { if (!installed) { vgaInit(); } displayReset(); } void displayExit(void) { if (!installed) { return; } vgaExit(); } /**************************************************************/ /**************************************************************/ #define MAX_MAKE 2 #define MAX_BREAK 3 typedef struct { unsigned int xKeycode; int pcNumMake; Byte pcKeyMake[MAX_MAKE]; int pcNumBreak; Byte pcKeyBreak[MAX_BREAK]; } Keycode; static Keycode kbdCodeTbl[] = { { 0x09, 1, { 0x76, 0x00 }, 2, { 0xF0, 0x76, 0x00 } }, { 0x43, 1, { 0x05, 0x00 }, 2, { 0xF0, 0x05, 0x00 } }, { 0x44, 1, { 0x06, 0x00 }, 2, { 0xF0, 0x06, 0x00 } }, { 0x45, 1, { 0x04, 0x00 }, 2, { 0xF0, 0x04, 0x00 } }, { 0x46, 1, { 0x0C, 0x00 }, 2, { 0xF0, 0x0C, 0x00 } }, { 0x47, 1, { 0x03, 0x00 }, 2, { 0xF0, 0x03, 0x00 } }, { 0x48, 1, { 0x0B, 0x00 }, 2, { 0xF0, 0x0B, 0x00 } }, { 0x49, 1, { 0x83, 0x00 }, 2, { 0xF0, 0x83, 0x00 } }, { 0x4A, 1, { 0x0A, 0x00 }, 2, { 0xF0, 0x0A, 0x00 } }, { 0x4B, 1, { 0x01, 0x00 }, 2, { 0xF0, 0x01, 0x00 } }, { 0x4C, 1, { 0x09, 0x00 }, 2, { 0xF0, 0x09, 0x00 } }, { 0x5F, 1, { 0x78, 0x00 }, 2, { 0xF0, 0x78, 0x00 } }, { 0x60, 1, { 0x07, 0x00 }, 2, { 0xF0, 0x07, 0x00 } }, /*------------------------------------------------*/ { 0x31, 1, { 0x0E, 0x00 }, 2, { 0xF0, 0x0E, 0x00 } }, { 0x0A, 1, { 0x16, 0x00 }, 2, { 0xF0, 0x16, 0x00 } }, { 0x0B, 1, { 0x1E, 0x00 }, 2, { 0xF0, 0x1E, 0x00 } }, { 0x0C, 1, { 0x26, 0x00 }, 2, { 0xF0, 0x26, 0x00 } }, { 0x0D, 1, { 0x25, 0x00 }, 2, { 0xF0, 0x25, 0x00 } }, { 0x0E, 1, { 0x2E, 0x00 }, 2, { 0xF0, 0x2E, 0x00 } }, { 0x0F, 1, { 0x36, 0x00 }, 2, { 0xF0, 0x36, 0x00 } }, { 0x10, 1, { 0x3D, 0x00 }, 2, { 0xF0, 0x3D, 0x00 } }, { 0x11, 1, { 0x3E, 0x00 }, 2, { 0xF0, 0x3E, 0x00 } }, { 0x12, 1, { 0x46, 0x00 }, 2, { 0xF0, 0x46, 0x00 } }, { 0x13, 1, { 0x45, 0x00 }, 2, { 0xF0, 0x45, 0x00 } }, { 0x14, 1, { 0x4E, 0x00 }, 2, { 0xF0, 0x4E, 0x00 } }, { 0x15, 1, { 0x55, 0x00 }, 2, { 0xF0, 0x55, 0x00 } }, { 0x16, 1, { 0x66, 0x00 }, 2, { 0xF0, 0x66, 0x00 } }, /*------------------------------------------------*/ { 0x17, 1, { 0x0D, 0x00 }, 2, { 0xF0, 0x0D, 0x00 } }, { 0x18, 1, { 0x15, 0x00 }, 2, { 0xF0, 0x15, 0x00 } }, { 0x19, 1, { 0x1D, 0x00 }, 2, { 0xF0, 0x1D, 0x00 } }, { 0x1A, 1, { 0x24, 0x00 }, 2, { 0xF0, 0x24, 0x00 } }, { 0x1B, 1, { 0x2D, 0x00 }, 2, { 0xF0, 0x2D, 0x00 } }, { 0x1C, 1, { 0x2C, 0x00 }, 2, { 0xF0, 0x2C, 0x00 } }, { 0x1D, 1, { 0x35, 0x00 }, 2, { 0xF0, 0x35, 0x00 } }, { 0x1E, 1, { 0x3C, 0x00 }, 2, { 0xF0, 0x3C, 0x00 } }, { 0x1F, 1, { 0x43, 0x00 }, 2, { 0xF0, 0x43, 0x00 } }, { 0x20, 1, { 0x44, 0x00 }, 2, { 0xF0, 0x44, 0x00 } }, { 0x21, 1, { 0x4D, 0x00 }, 2, { 0xF0, 0x4D, 0x00 } }, { 0x22, 1, { 0x54, 0x00 }, 2, { 0xF0, 0x54, 0x00 } }, { 0x23, 1, { 0x5B, 0x00 }, 2, { 0xF0, 0x5B, 0x00 } }, { 0x24, 1, { 0x5A, 0x00 }, 2, { 0xF0, 0x5A, 0x00 } }, /*------------------------------------------------*/ { 0x42, 1, { 0x58, 0x00 }, 2, { 0xF0, 0x58, 0x00 } }, { 0x26, 1, { 0x1C, 0x00 }, 2, { 0xF0, 0x1C, 0x00 } }, { 0x27, 1, { 0x1B, 0x00 }, 2, { 0xF0, 0x1B, 0x00 } }, { 0x28, 1, { 0x23, 0x00 }, 2, { 0xF0, 0x23, 0x00 } }, { 0x29, 1, { 0x2B, 0x00 }, 2, { 0xF0, 0x2B, 0x00 } }, { 0x2A, 1, { 0x34, 0x00 }, 2, { 0xF0, 0x34, 0x00 } }, { 0x2B, 1, { 0x33, 0x00 }, 2, { 0xF0, 0x33, 0x00 } }, { 0x2C, 1, { 0x3B, 0x00 }, 2, { 0xF0, 0x3B, 0x00 } }, { 0x2D, 1, { 0x42, 0x00 }, 2, { 0xF0, 0x42, 0x00 } }, { 0x2E, 1, { 0x4B, 0x00 }, 2, { 0xF0, 0x4B, 0x00 } }, { 0x2F, 1, { 0x4C, 0x00 }, 2, { 0xF0, 0x4C, 0x00 } }, { 0x30, 1, { 0x52, 0x00 }, 2, { 0xF0, 0x52, 0x00 } }, { 0x33, 1, { 0x5D, 0x00 }, 2, { 0xF0, 0x5D, 0x00 } }, /*------------------------------------------------*/ { 0x32, 1, { 0x12, 0x00 }, 2, { 0xF0, 0x12, 0x00 } }, { 0x5E, 1, { 0x61, 0x00 }, 2, { 0xF0, 0x61, 0x00 } }, { 0x34, 1, { 0x1A, 0x00 }, 2, { 0xF0, 0x1A, 0x00 } }, { 0x35, 1, { 0x22, 0x00 }, 2, { 0xF0, 0x22, 0x00 } }, { 0x36, 1, { 0x21, 0x00 }, 2, { 0xF0, 0x21, 0x00 } }, { 0x37, 1, { 0x2A, 0x00 }, 2, { 0xF0, 0x2A, 0x00 } }, { 0x38, 1, { 0x32, 0x00 }, 2, { 0xF0, 0x32, 0x00 } }, { 0x39, 1, { 0x31, 0x00 }, 2, { 0xF0, 0x31, 0x00 } }, { 0x3A, 1, { 0x3A, 0x00 }, 2, { 0xF0, 0x3A, 0x00 } }, { 0x3B, 1, { 0x41, 0x00 }, 2, { 0xF0, 0x41, 0x00 } }, { 0x3C, 1, { 0x49, 0x00 }, 2, { 0xF0, 0x49, 0x00 } }, { 0x3D, 1, { 0x4A, 0x00 }, 2, { 0xF0, 0x4A, 0x00 } }, { 0x3E, 1, { 0x59, 0x00 }, 2, { 0xF0, 0x59, 0x00 } }, /*------------------------------------------------*/ { 0x25, 1, { 0x14, 0x00 }, 2, { 0xF0, 0x14, 0x00 } }, { 0x73, 2, { 0xE0, 0x1F }, 3, { 0xE0, 0xF0, 0x1F } }, { 0x40, 1, { 0x11, 0x00 }, 2, { 0xF0, 0x11, 0x00 } }, { 0x41, 1, { 0x29, 0x00 }, 2, { 0xF0, 0x29, 0x00 } }, { 0x71, 2, { 0xE0, 0x11 }, 3, { 0xE0, 0xF0, 0x11 } }, { 0x74, 2, { 0xE0, 0x27 }, 3, { 0xE0, 0xF0, 0x27 } }, { 0x75, 2, { 0xE0, 0x2F }, 3, { 0xE0, 0xF0, 0x2F } }, { 0x6D, 2, { 0xE0, 0x14 }, 3, { 0xE0, 0xF0, 0x14 } }, /*------------------------------------------------*/ { 0x6A, 2, { 0xE0, 0x70 }, 3, { 0xE0, 0xF0, 0x70 } }, { 0x61, 2, { 0xE0, 0x6C }, 3, { 0xE0, 0xF0, 0x6C } }, { 0x63, 2, { 0xE0, 0x7D }, 3, { 0xE0, 0xF0, 0x7D } }, { 0x6B, 2, { 0xE0, 0x71 }, 3, { 0xE0, 0xF0, 0x71 } }, { 0x67, 2, { 0xE0, 0x69 }, 3, { 0xE0, 0xF0, 0x69 } }, { 0x69, 2, { 0xE0, 0x7A }, 3, { 0xE0, 0xF0, 0x7A } }, { 0x62, 2, { 0xE0, 0x75 }, 3, { 0xE0, 0xF0, 0x75 } }, { 0x64, 2, { 0xE0, 0x6B }, 3, { 0xE0, 0xF0, 0x6B } }, { 0x68, 2, { 0xE0, 0x72 }, 3, { 0xE0, 0xF0, 0x72 } }, { 0x66, 2, { 0xE0, 0x74 }, 3, { 0xE0, 0xF0, 0x74 } }, /*------------------------------------------------*/ { 0x4D, 1, { 0x77, 0x00 }, 2, { 0xF0, 0x77, 0x00 } }, { 0x70, 2, { 0xE0, 0x4A }, 3, { 0xE0, 0xF0, 0x4A } }, { 0x3F, 1, { 0x7C, 0x00 }, 2, { 0xF0, 0x7C, 0x00 } }, { 0x52, 1, { 0x7B, 0x00 }, 2, { 0xF0, 0x7B, 0x00 } }, { 0x4F, 1, { 0x6C, 0x00 }, 2, { 0xF0, 0x6C, 0x00 } }, { 0x50, 1, { 0x75, 0x00 }, 2, { 0xF0, 0x75, 0x00 } }, { 0x51, 1, { 0x7D, 0x00 }, 2, { 0xF0, 0x7D, 0x00 } }, { 0x56, 1, { 0x79, 0x00 }, 2, { 0xF0, 0x79, 0x00 } }, { 0x53, 1, { 0x6B, 0x00 }, 2, { 0xF0, 0x6B, 0x00 } }, { 0x54, 1, { 0x73, 0x00 }, 2, { 0xF0, 0x73, 0x00 } }, { 0x55, 1, { 0x74, 0x00 }, 2, { 0xF0, 0x74, 0x00 } }, { 0x57, 1, { 0x69, 0x00 }, 2, { 0xF0, 0x69, 0x00 } }, { 0x58, 1, { 0x72, 0x00 }, 2, { 0xF0, 0x72, 0x00 } }, { 0x59, 1, { 0x7A, 0x00 }, 2, { 0xF0, 0x7A, 0x00 } }, { 0x6C, 2, { 0xE0, 0x5A }, 3, { 0xE0, 0xF0, 0x5A } }, { 0x5A, 1, { 0x70, 0x00 }, 2, { 0xF0, 0x70, 0x00 } }, { 0x5B, 1, { 0x71, 0x00 }, 2, { 0xF0, 0x71, 0x00 } }, }; static int keycodeCompare(const void *code1, const void *code2) { return ((Keycode *) code1)->xKeycode - ((Keycode *) code2)->xKeycode; } static void initKeycode(void) { qsort(kbdCodeTbl, sizeof(kbdCodeTbl)/sizeof(kbdCodeTbl[0]), sizeof(kbdCodeTbl[0]), keycodeCompare); } static Keycode *lookupKeycode(unsigned int xKeycode) { int lo, hi, tst; int res; lo = 0; hi = sizeof(kbdCodeTbl) / sizeof(kbdCodeTbl[0]) - 1; while (lo <= hi) { tst = (lo + hi) / 2; res = kbdCodeTbl[tst].xKeycode - xKeycode; if (res == 0) { return &kbdCodeTbl[tst]; } if (res < 0) { lo = tst + 1; } else { hi = tst - 1; } } return NULL; } /**************************************************************/ #define KBD_BUF_MAX 100 #define KBD_BUF_NEXT(p) (((p) + 1) % KBD_BUF_MAX) static Byte kbdBuf[KBD_BUF_MAX]; static int kbdBufWritePtr; static int kbdBufReadPtr; static void kbdBufInit(void) { initKeycode(); kbdBufWritePtr = 0; kbdBufReadPtr = 0; } static int kbdBufFree(void) { if (kbdBufReadPtr <= kbdBufWritePtr) { return KBD_BUF_MAX - (kbdBufWritePtr - kbdBufReadPtr) - 1; } else { return (kbdBufReadPtr - kbdBufWritePtr) - 1; } } static void keyPressed(unsigned int xKeycode) { Keycode *p; int i; if (debugKeycode) { cPrintf("**** KEY PRESSED: 0x%08X ****\n", xKeycode); } p = lookupKeycode(xKeycode); if (p == NULL) { /* keycode not found */ return; } if (kbdBufFree() < (MAX_MAKE + MAX_BREAK) * 4) { /* buffer full */ return; } for (i = 0; i < p->pcNumMake; i++) { kbdBuf[kbdBufWritePtr] = p->pcKeyMake[i]; kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr); } } static void keyReleased(unsigned int xKeycode) { Keycode *p; int i; if (debugKeycode) { cPrintf("**** KEY RELEASED: 0x%08X ****\n", xKeycode); } p = lookupKeycode(xKeycode); if (p == NULL) { /* keycode not found */ return; } if (kbdBufFree() < MAX_BREAK * 4) { /* buffer full */ return; } for (i = 0; i < p->pcNumBreak; i++) { kbdBuf[kbdBufWritePtr] = p->pcKeyBreak[i]; kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr); } } /**************************************************************/ static Word kbdCtrl; static Word kbdData; static void kbdCallback(int dev) { if (debug) { cPrintf("\n**** KEYBOARD CALLBACK ****\n"); } timerStart(KEYBOARD_USEC, kbdCallback, dev); if (kbdBufWritePtr == kbdBufReadPtr) { /* no character ready */ return; } /* any character typed */ kbdData = kbdBuf[kbdBufReadPtr]; kbdBufReadPtr = KBD_BUF_NEXT(kbdBufReadPtr); kbdCtrl |= KEYBOARD_RDY; if (kbdCtrl & KEYBOARD_IEN) { /* raise keyboard interrupt */ cpuSetInterrupt(IRQ_KEYBOARD); } } Word keyboardRead(Word addr) { Word data; if (debug) { cPrintf("\n**** KEYBOARD READ from 0x%08X", addr); } if (!installed) { throwException(EXC_BUS_TIMEOUT); } if (addr == KEYBOARD_CTRL) { data = kbdCtrl; } else if (addr == KEYBOARD_DATA) { kbdCtrl &= ~KEYBOARD_RDY; if (kbdCtrl & KEYBOARD_IEN) { /* lower keyboard interrupt */ cpuResetInterrupt(IRQ_KEYBOARD); } data = kbdData; } else { /* illegal register */ throwException(EXC_BUS_TIMEOUT); } if (debug) { cPrintf(", data = 0x%08X ****\n", data); } return data; } void keyboardWrite(Word addr, Word data) { if (debug) { cPrintf("\n**** KEYBOARD WRITE to 0x%08X, data = 0x%08X ****\n", addr, data); } if (!installed) { throwException(EXC_BUS_TIMEOUT); } if (addr == KEYBOARD_CTRL) { if (data & KEYBOARD_IEN) { kbdCtrl |= KEYBOARD_IEN; } else { kbdCtrl &= ~KEYBOARD_IEN; } if (data & KEYBOARD_RDY) { kbdCtrl |= KEYBOARD_RDY; } else { kbdCtrl &= ~KEYBOARD_RDY; } if ((kbdCtrl & KEYBOARD_IEN) != 0 && (kbdCtrl & KEYBOARD_RDY) != 0) { /* raise keyboard interrupt */ cpuSetInterrupt(IRQ_KEYBOARD); } else { /* lower keyboard interrupt */ cpuResetInterrupt(IRQ_KEYBOARD); } } else if (addr == KEYBOARD_DATA) { /* this register is read-only */ throwException(EXC_BUS_TIMEOUT); } else { /* illegal register */ throwException(EXC_BUS_TIMEOUT); } } void keyboardReset(void) { if (!installed) { return; } cPrintf("Resetting Keyboard...\n"); kbdBufInit(); kbdCtrl = 0; kbdData = 0; timerStart(KEYBOARD_USEC, kbdCallback, 0); } void keyboardInit(void) { if (!installed) { vgaInit(); } keyboardReset(); } void keyboardExit(void) { if (!installed) { return; } vgaExit(); }
Go to most recent revision | Compare with Previous | Blame | View Log