OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [dspkbd.c] - Blame information for rev 251

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 hellwig
/*
2 25 hellwig
 * dspkbd.h -- display & keyboard controller simulation
3 8 hellwig
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <setjmp.h>
10
 
11
#include "common.h"
12
#include "console.h"
13
#include "error.h"
14
#include "except.h"
15
#include "cpu.h"
16
#include "timer.h"
17
#include "dspkbd.h"
18
 
19
 
20
static Bool debug = false;
21
static Bool debugKeycode = false;
22 251 hellwig
static Bool volatile installed = false;
23 8 hellwig
 
24
 
25
static void blinkScreen(void);
26
 
27
static void keyPressed(unsigned int xKeycode);
28
static void keyReleased(unsigned int xKeycode);
29
 
30
 
31
/**************************************************************/
32
/**************************************************************/
33
 
34
/* common definitions, global variables */
35
 
36
 
37
#include <pthread.h>
38
#include <unistd.h>
39
#include <time.h>
40
#include <X11/Xlib.h>
41
#include <X11/Xutil.h>
42
#include <X11/Xatom.h>
43
 
44
 
45
#define WINDOW_SIZE_X           640
46
#define WINDOW_SIZE_Y           480
47
#define WINDOW_POS_X            100
48
#define WINDOW_POS_Y            100
49
 
50
 
51
#define C2B(c,ch)               (((((c) & 0xFF) * ch.scale) >> 8) * ch.factor)
52 251 hellwig
#define RGB2PIXEL(r,g,b)        (0xFF000000 | \
53
                                 C2B(r, vga.red) | \
54 8 hellwig
                                 C2B(g, vga.green) | \
55
                                 C2B(b, vga.blue))
56
 
57
 
58
typedef struct {
59
  unsigned long scale;
60
  unsigned long factor;
61
} ColorChannel;
62
 
63
 
64
typedef struct {
65
  int argc;
66
  char **argv;
67
  Display *display;
68
  Window win;
69
  GC gc;
70
  XImage *image;
71
  ColorChannel red, green, blue;
72
  XExposeEvent expose;
73
  XClientMessageEvent shutdown;
74
} VGA;
75
 
76
 
77
static VGA vga;
78
 
79
 
80
/**************************************************************/
81
 
82
/* monitor server */
83
 
84
 
85
static ColorChannel mask2channel(unsigned long mask) {
86
  unsigned long f;
87
  ColorChannel ch;
88
 
89
  if (mask == 0) {
90
    error("color mask is 0 in mask2channel");
91
  }
92
  for (f = 1; (mask & 1) == 0; f <<= 1) {
93
    mask >>= 1;
94
  }
95
  ch.factor = f;
96
  ch.scale = mask + 1;
97
  while ((mask & 1) != 0) {
98
    mask >>= 1;
99
  }
100
  if (mask != 0) {
101
    error("scattered color mask bits in mask2channel");
102
  }
103
  return ch;
104
}
105
 
106
 
107
static void initMonitor(int argc, char *argv[]) {
108
  int screenNum;
109
  Window rootWin;
110
  XVisualInfo visualTemp;
111
  XVisualInfo *visualInfo;
112
  int visualCount;
113
  int bestMatch;
114
  int bestDepth;
115
  Visual *visual;
116
  int i;
117
  unsigned long pixel;
118
  int x, y;
119
  Colormap colormap;
120
  XSetWindowAttributes attrib;
121
  XSizeHints *sizeHints;
122
  XWMHints *wmHints;
123
  XClassHint *classHints;
124
  XTextProperty windowName;
125
  XGCValues gcValues;
126
 
127
  /* connect to X server */
128
  if (XInitThreads() == 0) {
129
    error("no thread support for X11");
130
  }
131
  vga.display = XOpenDisplay(NULL);
132
  if (vga.display == NULL) {
133
    error("cannot connect to X server");
134
  }
135
  screenNum = DefaultScreen(vga.display);
136
  rootWin = RootWindow(vga.display, screenNum);
137
  /* find TrueColor visual */
138
  visualTemp.screen = screenNum;
139
  visualTemp.class = TrueColor;
140
  visualInfo = XGetVisualInfo(vga.display,
141
                              VisualClassMask | VisualScreenMask,
142
                              &visualTemp, &visualCount);
143
  if (visualInfo == NULL || visualCount == 0) {
144
    error("no TrueColor visual found");
145
  }
146
  bestMatch = 0;
147
  bestDepth = visualInfo[0].depth;
148
  visual = visualInfo[0].visual;
149
  for (i = 1; i < visualCount; i++) {
150
    if (visualInfo[i].depth > bestDepth) {
151
      bestMatch = i;
152
      bestDepth = visualInfo[i].depth;
153
      visual = visualInfo[i].visual;
154
    }
155
  }
156
  /* build color channels */
157
  vga.red = mask2channel(visualInfo[bestMatch].red_mask);
158
  vga.green = mask2channel(visualInfo[bestMatch].green_mask);
159
  vga.blue = mask2channel(visualInfo[bestMatch].blue_mask);
160
  /* create and initialize image */
161
  vga.image = XCreateImage(vga.display, visual, bestDepth, ZPixmap,
162
                           0, NULL, WINDOW_SIZE_X, WINDOW_SIZE_Y, 32, 0);
163
  if (vga.image == NULL) {
164
    error("cannot allocate image");
165
  }
166
  vga.image->data = malloc(vga.image->height * vga.image->bytes_per_line);
167
  if (vga.image->data == NULL) {
168
    error("cannot allocate image memory");
169
  }
170
  pixel = RGB2PIXEL(0, 0, 0);
171
  for (y = 0; y < WINDOW_SIZE_Y; y++) {
172
    for (x = 0; x < WINDOW_SIZE_X; x++) {
173
      XPutPixel(vga.image, x, y, pixel);
174
    }
175
  }
176
  /* allocate a colormap */
177
  colormap = XCreateColormap(vga.display, rootWin, visual, AllocNone);
178
  /* create the window */
179
  attrib.colormap = colormap;
180
  attrib.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask;
181
  attrib.background_pixel = RGB2PIXEL(0, 0, 0);
182
  attrib.border_pixel = RGB2PIXEL(0, 0, 0);
183
  vga.win =
184
    XCreateWindow(vga.display, rootWin,
185
                  WINDOW_POS_X, WINDOW_POS_Y,
186
                  WINDOW_SIZE_X, WINDOW_SIZE_Y,
187
                  0, bestDepth, InputOutput, visual,
188
                  CWEventMask | CWColormap | CWBackPixel | CWBorderPixel,
189
                  &attrib);
190
  /* give hints to window manager */
191
  sizeHints = XAllocSizeHints();
192
  wmHints = XAllocWMHints();
193
  classHints = XAllocClassHint();
194
  if (sizeHints == NULL ||
195
      wmHints == NULL ||
196
      classHints == NULL) {
197
    error("hint allocation failed");
198
  }
199
  sizeHints->flags = PMinSize | PMaxSize;
200
  sizeHints->min_width = WINDOW_SIZE_X;
201
  sizeHints->min_height = WINDOW_SIZE_Y;
202
  sizeHints->max_width = WINDOW_SIZE_X;
203
  sizeHints->max_height = WINDOW_SIZE_Y;
204
  wmHints->flags = StateHint | InputHint;
205
  wmHints->input = True;
206
  wmHints->initial_state = NormalState;
207 159 hellwig
  classHints->res_name = "ECO32 Console";
208 8 hellwig
  classHints->res_class = "ECO32";
209
  if (XStringListToTextProperty(&classHints->res_name, 1, &windowName) == 0) {
210
    error("property allocation failed");
211
  }
212
  XSetWMProperties(vga.display, vga.win, &windowName, NULL,
213
                   argv, argc, sizeHints, wmHints, classHints);
214
  /* create a GC */
215
  vga.gc = XCreateGC(vga.display, vga.win, 0, &gcValues);
216
  /* finally get the window displayed */
217
  XMapWindow(vga.display, vga.win);
218
  /* prepare expose event */
219
  vga.expose.type = Expose;
220
  vga.expose.display = vga.display;
221
  vga.expose.window = vga.win;
222
  vga.expose.x = 0;
223
  vga.expose.y = 0;
224
  vga.expose.width = WINDOW_SIZE_X;
225
  vga.expose.height = WINDOW_SIZE_Y;
226
  vga.expose.count = 0;
227
  /* prepare shutdown event */
228
  vga.shutdown.type = ClientMessage;
229
  vga.shutdown.display = vga.display;
230
  vga.shutdown.window = vga.win;
231
  vga.shutdown.message_type = XA_WM_COMMAND;
232 251 hellwig
  vga.shutdown.format = 8;
233 8 hellwig
  /* say that the graphics controller is installed */
234
  XSync(vga.display, False);
235
  installed = true;
236
}
237
 
238
 
239
static void exitMonitor(void) {
240
  XFreeGC(vga.display, vga.gc);
241
  XUnmapWindow(vga.display, vga.win);
242
  XDestroyWindow(vga.display, vga.win);
243
  XDestroyImage(vga.image);
244
  XCloseDisplay(vga.display);
245
  installed = false;
246
}
247
 
248
 
249
static int ioErrorHandler(Display *display) {
250
  error("connection to monitor window lost");
251
  /* never reached */
252
  return 0;
253
}
254
 
255
 
256
static void *server(void *ignore) {
257
  Bool run;
258
  XEvent event;
259
 
260
  initMonitor(vga.argc, vga.argv);
261
  XSetIOErrorHandler(ioErrorHandler);
262
  run = true;
263
  while (run) {
264
    XNextEvent(vga.display, &event);
265
    switch (event.type) {
266
      case Expose:
267
        blinkScreen();
268
        XPutImage(vga.display, vga.win, vga.gc, vga.image,
269
                  event.xexpose.x, event.xexpose.y,
270
                  event.xexpose.x, event.xexpose.y,
271
                  event.xexpose.width, event.xexpose.height);
272
        break;
273
      case ClientMessage:
274
        if (event.xclient.message_type == XA_WM_COMMAND &&
275 251 hellwig
            event.xclient.format == 8) {
276 8 hellwig
          run = false;
277
        }
278
        break;
279
      case KeyPress:
280
        keyPressed(event.xkey.keycode);
281
        break;
282
      case KeyRelease:
283
        keyReleased(event.xkey.keycode);
284
        break;
285
      default:
286
        break;
287
    }
288
  }
289
  exitMonitor();
290
  return NULL;
291
}
292
 
293
 
294
/**************************************************************/
295
 
296
/* refresh timer */
297
 
298
 
299 251 hellwig
static Bool volatile refreshRunning = false;
300
static Bool volatile blink = false;
301 8 hellwig
 
302
 
303
static void *refresh(void *ignore) {
304
  static int blinkCounter = 0;
305
  struct timespec delay;
306
 
307
  while (refreshRunning) {
308
    if (++blinkCounter == 5) {
309
      blinkCounter = 0;
310
      blink = !blink;
311
    }
312
    XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.expose);
313
    XFlush(vga.display);
314
    delay.tv_sec = 0;
315
    delay.tv_nsec = 100 * 1000 * 1000;
316
    nanosleep(&delay, &delay);
317
  }
318
  return NULL;
319
}
320
 
321
 
322
/**************************************************************/
323
 
324
/* server interface */
325
 
326
 
327
static int myArgc = 1;
328
static char *myArgv[] = {
329
  "eco32",
330
  NULL
331
};
332
 
333 251 hellwig
static pthread_t monitorThread;
334
static pthread_t refreshThread;
335 8 hellwig
 
336 251 hellwig
 
337 8 hellwig
static void vgaInit(void) {
338
  /* start monitor server in a separate thread */
339
  vga.argc = myArgc;
340
  vga.argv = myArgv;
341 251 hellwig
  if (pthread_create(&monitorThread, NULL, server, NULL) != 0) {
342 8 hellwig
    error("cannot start monitor server");
343
  }
344 251 hellwig
  while (!installed) ;
345 8 hellwig
  /* start refresh timer in another thread */
346
  refreshRunning = true;
347 251 hellwig
  if (pthread_create(&refreshThread, NULL, refresh, NULL) != 0) {
348 8 hellwig
    error("cannot start refresh timer");
349
  }
350
}
351
 
352
 
353
static void vgaExit(void) {
354
  refreshRunning = false;
355 251 hellwig
  pthread_join(refreshThread, NULL);
356 8 hellwig
  XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.shutdown);
357
  XSync(vga.display, False);
358 251 hellwig
  pthread_join(monitorThread, NULL);
359 8 hellwig
}
360
 
361
 
362
static void vgaWrite(int x, int y, int r, int g, int b) {
363
  XPutPixel(vga.image, x, y, RGB2PIXEL(r, g, b));
364
}
365
 
366
 
367
/**************************************************************/
368
/**************************************************************/
369
 
370
 
371
#define CELL_SIZE_X     8
372
#define CELL_SIZE_Y     16
373
 
374
#define TEXT_SIZE_X     (WINDOW_SIZE_X / CELL_SIZE_X)
375
#define TEXT_SIZE_Y     (WINDOW_SIZE_Y / CELL_SIZE_Y)
376
 
377
 
378
static Half text[TEXT_SIZE_Y][TEXT_SIZE_X];
379
 
380
static Byte font[] = {
381
#include "font"
382
};
383
 
384
 
385
static void updateCharacter(int x, int y, Half c) {
386
  int xx, yy;
387
  int i, j;
388
  Byte pixels;
389
  int r, g, b;
390
 
391
  xx = x * CELL_SIZE_X;
392
  yy = y * CELL_SIZE_Y;
393
  for (j = 0; j < CELL_SIZE_Y; j++) {
394
    pixels = font[(c & 0x00FF) * CELL_SIZE_Y + j];
395
    for (i = 0; i < CELL_SIZE_X; i++) {
396
      if ((pixels & (1 << (CELL_SIZE_X - 1 - i))) != 0 &&
397
          !((c & 0x8000) != 0 && blink)) {
398
        /* foreground */
399
        if (c & 0x0800) {
400
          /* intensify bit is on */
401
          r = (c & 0x0400) ? 255 : 73;
402
          g = (c & 0x0200) ? 255 : 73;
403
          b = (c & 0x0100) ? 255 : 73;
404
        } else {
405
          /* intensify bit is off */
406
          r = (c & 0x0400) ? 146 : 0;
407
          g = (c & 0x0200) ? 146 : 0;
408
          b = (c & 0x0100) ? 146 : 0;
409
        }
410
      } else {
411
        /* background */
412
        r = (c & 0x4000) ? 146 : 0;
413
        g = (c & 0x2000) ? 146 : 0;
414
        b = (c & 0x1000) ? 146 : 0;
415
      }
416
      vgaWrite(xx + i, yy + j, r, g, b);
417
    }
418
  }
419
}
420
 
421
 
422
static void blinkScreen(void) {
423
  static Bool previousBlink = false;
424
  int x, y;
425
  Half c;
426
 
427
  if (previousBlink == blink) {
428
    /* blink state didn't change, nothing to do */
429
    return;
430
  }
431
  previousBlink = blink;
432
  for (y = 0; y < TEXT_SIZE_Y; y++) {
433
    for (x = 0; x < TEXT_SIZE_X; x++) {
434
      /* update the character if it is blinking */
435
      c = text[y][x];
436
      if (c & 0x8000) {
437
        updateCharacter(x, y, c);
438
      }
439
    }
440
  }
441
}
442
 
443
 
444
static Half readCharAndAttr(int x, int y) {
445
  return text[y][x];
446
}
447
 
448
 
449
static void writeCharAndAttr(int x, int y, Half c) {
450
  text[y][x] = c;
451
  updateCharacter(x, y, c);
452
}
453
 
454
 
455
static char *screen[] = {
456
#include "screen"
457
};
458
 
459
 
460
static void loadSplashScreen(void) {
461
  int x, y;
462
  char *p;
463
 
464
  for (y = 0; y < TEXT_SIZE_Y; y++) {
465
    p = screen[y];
466
    for (x = 0; x < TEXT_SIZE_X; x++) {
467
      writeCharAndAttr(x, y, (Half) 0x0700 | (Half) *p);
468
      p++;
469
    }
470
  }
471
}
472
 
473
 
474
/**************************************************************/
475
 
476
 
477
Word displayRead(Word addr) {
478
  int x, y;
479
  Word data;
480
 
481
  if (debug) {
482
    cPrintf("\n**** DISPLAY READ from 0x%08X", addr);
483
  }
484
  if (!installed) {
485
    throwException(EXC_BUS_TIMEOUT);
486
  }
487
  x = (addr >> 2) & ((1 << 7) - 1);
488
  y = (addr >> 9) & ((1 << 5) - 1);
489
  if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) {
490
    throwException(EXC_BUS_TIMEOUT);
491
  }
492
  data = readCharAndAttr(x, y);
493
  if (debug) {
494
    cPrintf(", data = 0x%08X ****\n", data);
495
  }
496
  return data;
497
}
498
 
499
 
500
void displayWrite(Word addr, Word data) {
501
  int x, y;
502
 
503
  if (debug) {
504
    cPrintf("\n**** DISPLAY WRITE to 0x%08X, data = 0x%08X ****\n",
505
            addr, data);
506
  }
507
  if (!installed) {
508
    throwException(EXC_BUS_TIMEOUT);
509
  }
510
  x = (addr >> 2) & ((1 << 7) - 1);
511
  y = (addr >> 9) & ((1 << 5) - 1);
512
  if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) {
513
    throwException(EXC_BUS_TIMEOUT);
514
  }
515
  writeCharAndAttr(x, y, data);
516
}
517
 
518
 
519
void displayReset(void) {
520
  if (!installed) {
521
    return;
522
  }
523
  cPrintf("Resetting Display...\n");
524
  loadSplashScreen();
525
}
526
 
527
 
528
void displayInit(void) {
529
  if (!installed) {
530
    vgaInit();
531
  }
532
  displayReset();
533
}
534
 
535
 
536
void displayExit(void) {
537
  if (!installed) {
538
    return;
539
  }
540
  vgaExit();
541
}
542
 
543
 
544
/**************************************************************/
545
/**************************************************************/
546
 
547
 
548
#define MAX_MAKE        2
549
#define MAX_BREAK       3
550
 
551
 
552
typedef struct {
553
  unsigned int xKeycode;
554
  int pcNumMake;
555
  Byte pcKeyMake[MAX_MAKE];
556
  int pcNumBreak;
557
  Byte pcKeyBreak[MAX_BREAK];
558
} Keycode;
559
 
560
 
561
static Keycode kbdCodeTbl[] = {
562
  { 0x09, 1, { 0x76, 0x00 }, 2, { 0xF0, 0x76, 0x00 } },
563
  { 0x43, 1, { 0x05, 0x00 }, 2, { 0xF0, 0x05, 0x00 } },
564
  { 0x44, 1, { 0x06, 0x00 }, 2, { 0xF0, 0x06, 0x00 } },
565
  { 0x45, 1, { 0x04, 0x00 }, 2, { 0xF0, 0x04, 0x00 } },
566
  { 0x46, 1, { 0x0C, 0x00 }, 2, { 0xF0, 0x0C, 0x00 } },
567
  { 0x47, 1, { 0x03, 0x00 }, 2, { 0xF0, 0x03, 0x00 } },
568
  { 0x48, 1, { 0x0B, 0x00 }, 2, { 0xF0, 0x0B, 0x00 } },
569
  { 0x49, 1, { 0x83, 0x00 }, 2, { 0xF0, 0x83, 0x00 } },
570
  { 0x4A, 1, { 0x0A, 0x00 }, 2, { 0xF0, 0x0A, 0x00 } },
571
  { 0x4B, 1, { 0x01, 0x00 }, 2, { 0xF0, 0x01, 0x00 } },
572
  { 0x4C, 1, { 0x09, 0x00 }, 2, { 0xF0, 0x09, 0x00 } },
573
  { 0x5F, 1, { 0x78, 0x00 }, 2, { 0xF0, 0x78, 0x00 } },
574
  { 0x60, 1, { 0x07, 0x00 }, 2, { 0xF0, 0x07, 0x00 } },
575
  /*------------------------------------------------*/
576
  { 0x31, 1, { 0x0E, 0x00 }, 2, { 0xF0, 0x0E, 0x00 } },
577
  { 0x0A, 1, { 0x16, 0x00 }, 2, { 0xF0, 0x16, 0x00 } },
578
  { 0x0B, 1, { 0x1E, 0x00 }, 2, { 0xF0, 0x1E, 0x00 } },
579
  { 0x0C, 1, { 0x26, 0x00 }, 2, { 0xF0, 0x26, 0x00 } },
580
  { 0x0D, 1, { 0x25, 0x00 }, 2, { 0xF0, 0x25, 0x00 } },
581
  { 0x0E, 1, { 0x2E, 0x00 }, 2, { 0xF0, 0x2E, 0x00 } },
582
  { 0x0F, 1, { 0x36, 0x00 }, 2, { 0xF0, 0x36, 0x00 } },
583
  { 0x10, 1, { 0x3D, 0x00 }, 2, { 0xF0, 0x3D, 0x00 } },
584
  { 0x11, 1, { 0x3E, 0x00 }, 2, { 0xF0, 0x3E, 0x00 } },
585
  { 0x12, 1, { 0x46, 0x00 }, 2, { 0xF0, 0x46, 0x00 } },
586
  { 0x13, 1, { 0x45, 0x00 }, 2, { 0xF0, 0x45, 0x00 } },
587
  { 0x14, 1, { 0x4E, 0x00 }, 2, { 0xF0, 0x4E, 0x00 } },
588
  { 0x15, 1, { 0x55, 0x00 }, 2, { 0xF0, 0x55, 0x00 } },
589
  { 0x16, 1, { 0x66, 0x00 }, 2, { 0xF0, 0x66, 0x00 } },
590
  /*------------------------------------------------*/
591
  { 0x17, 1, { 0x0D, 0x00 }, 2, { 0xF0, 0x0D, 0x00 } },
592
  { 0x18, 1, { 0x15, 0x00 }, 2, { 0xF0, 0x15, 0x00 } },
593
  { 0x19, 1, { 0x1D, 0x00 }, 2, { 0xF0, 0x1D, 0x00 } },
594
  { 0x1A, 1, { 0x24, 0x00 }, 2, { 0xF0, 0x24, 0x00 } },
595
  { 0x1B, 1, { 0x2D, 0x00 }, 2, { 0xF0, 0x2D, 0x00 } },
596
  { 0x1C, 1, { 0x2C, 0x00 }, 2, { 0xF0, 0x2C, 0x00 } },
597
  { 0x1D, 1, { 0x35, 0x00 }, 2, { 0xF0, 0x35, 0x00 } },
598
  { 0x1E, 1, { 0x3C, 0x00 }, 2, { 0xF0, 0x3C, 0x00 } },
599
  { 0x1F, 1, { 0x43, 0x00 }, 2, { 0xF0, 0x43, 0x00 } },
600
  { 0x20, 1, { 0x44, 0x00 }, 2, { 0xF0, 0x44, 0x00 } },
601
  { 0x21, 1, { 0x4D, 0x00 }, 2, { 0xF0, 0x4D, 0x00 } },
602
  { 0x22, 1, { 0x54, 0x00 }, 2, { 0xF0, 0x54, 0x00 } },
603
  { 0x23, 1, { 0x5B, 0x00 }, 2, { 0xF0, 0x5B, 0x00 } },
604
  { 0x24, 1, { 0x5A, 0x00 }, 2, { 0xF0, 0x5A, 0x00 } },
605
  /*------------------------------------------------*/
606
  { 0x42, 1, { 0x58, 0x00 }, 2, { 0xF0, 0x58, 0x00 } },
607
  { 0x26, 1, { 0x1C, 0x00 }, 2, { 0xF0, 0x1C, 0x00 } },
608
  { 0x27, 1, { 0x1B, 0x00 }, 2, { 0xF0, 0x1B, 0x00 } },
609
  { 0x28, 1, { 0x23, 0x00 }, 2, { 0xF0, 0x23, 0x00 } },
610
  { 0x29, 1, { 0x2B, 0x00 }, 2, { 0xF0, 0x2B, 0x00 } },
611
  { 0x2A, 1, { 0x34, 0x00 }, 2, { 0xF0, 0x34, 0x00 } },
612
  { 0x2B, 1, { 0x33, 0x00 }, 2, { 0xF0, 0x33, 0x00 } },
613
  { 0x2C, 1, { 0x3B, 0x00 }, 2, { 0xF0, 0x3B, 0x00 } },
614
  { 0x2D, 1, { 0x42, 0x00 }, 2, { 0xF0, 0x42, 0x00 } },
615
  { 0x2E, 1, { 0x4B, 0x00 }, 2, { 0xF0, 0x4B, 0x00 } },
616
  { 0x2F, 1, { 0x4C, 0x00 }, 2, { 0xF0, 0x4C, 0x00 } },
617
  { 0x30, 1, { 0x52, 0x00 }, 2, { 0xF0, 0x52, 0x00 } },
618
  { 0x33, 1, { 0x5D, 0x00 }, 2, { 0xF0, 0x5D, 0x00 } },
619
  /*------------------------------------------------*/
620
  { 0x32, 1, { 0x12, 0x00 }, 2, { 0xF0, 0x12, 0x00 } },
621
  { 0x5E, 1, { 0x61, 0x00 }, 2, { 0xF0, 0x61, 0x00 } },
622
  { 0x34, 1, { 0x1A, 0x00 }, 2, { 0xF0, 0x1A, 0x00 } },
623
  { 0x35, 1, { 0x22, 0x00 }, 2, { 0xF0, 0x22, 0x00 } },
624
  { 0x36, 1, { 0x21, 0x00 }, 2, { 0xF0, 0x21, 0x00 } },
625
  { 0x37, 1, { 0x2A, 0x00 }, 2, { 0xF0, 0x2A, 0x00 } },
626
  { 0x38, 1, { 0x32, 0x00 }, 2, { 0xF0, 0x32, 0x00 } },
627
  { 0x39, 1, { 0x31, 0x00 }, 2, { 0xF0, 0x31, 0x00 } },
628
  { 0x3A, 1, { 0x3A, 0x00 }, 2, { 0xF0, 0x3A, 0x00 } },
629
  { 0x3B, 1, { 0x41, 0x00 }, 2, { 0xF0, 0x41, 0x00 } },
630
  { 0x3C, 1, { 0x49, 0x00 }, 2, { 0xF0, 0x49, 0x00 } },
631
  { 0x3D, 1, { 0x4A, 0x00 }, 2, { 0xF0, 0x4A, 0x00 } },
632
  { 0x3E, 1, { 0x59, 0x00 }, 2, { 0xF0, 0x59, 0x00 } },
633
  /*------------------------------------------------*/
634
  { 0x25, 1, { 0x14, 0x00 }, 2, { 0xF0, 0x14, 0x00 } },
635
  { 0x73, 2, { 0xE0, 0x1F }, 3, { 0xE0, 0xF0, 0x1F } },
636
  { 0x40, 1, { 0x11, 0x00 }, 2, { 0xF0, 0x11, 0x00 } },
637
  { 0x41, 1, { 0x29, 0x00 }, 2, { 0xF0, 0x29, 0x00 } },
638
  { 0x71, 2, { 0xE0, 0x11 }, 3, { 0xE0, 0xF0, 0x11 } },
639
  { 0x74, 2, { 0xE0, 0x27 }, 3, { 0xE0, 0xF0, 0x27 } },
640
  { 0x75, 2, { 0xE0, 0x2F }, 3, { 0xE0, 0xF0, 0x2F } },
641
  { 0x6D, 2, { 0xE0, 0x14 }, 3, { 0xE0, 0xF0, 0x14 } },
642
  /*------------------------------------------------*/
643
  { 0x6A, 2, { 0xE0, 0x70 }, 3, { 0xE0, 0xF0, 0x70 } },
644
  { 0x61, 2, { 0xE0, 0x6C }, 3, { 0xE0, 0xF0, 0x6C } },
645
  { 0x63, 2, { 0xE0, 0x7D }, 3, { 0xE0, 0xF0, 0x7D } },
646
  { 0x6B, 2, { 0xE0, 0x71 }, 3, { 0xE0, 0xF0, 0x71 } },
647
  { 0x67, 2, { 0xE0, 0x69 }, 3, { 0xE0, 0xF0, 0x69 } },
648
  { 0x69, 2, { 0xE0, 0x7A }, 3, { 0xE0, 0xF0, 0x7A } },
649
  { 0x62, 2, { 0xE0, 0x75 }, 3, { 0xE0, 0xF0, 0x75 } },
650
  { 0x64, 2, { 0xE0, 0x6B }, 3, { 0xE0, 0xF0, 0x6B } },
651
  { 0x68, 2, { 0xE0, 0x72 }, 3, { 0xE0, 0xF0, 0x72 } },
652
  { 0x66, 2, { 0xE0, 0x74 }, 3, { 0xE0, 0xF0, 0x74 } },
653
  /*------------------------------------------------*/
654
  { 0x4D, 1, { 0x77, 0x00 }, 2, { 0xF0, 0x77, 0x00 } },
655
  { 0x70, 2, { 0xE0, 0x4A }, 3, { 0xE0, 0xF0, 0x4A } },
656
  { 0x3F, 1, { 0x7C, 0x00 }, 2, { 0xF0, 0x7C, 0x00 } },
657
  { 0x52, 1, { 0x7B, 0x00 }, 2, { 0xF0, 0x7B, 0x00 } },
658
  { 0x4F, 1, { 0x6C, 0x00 }, 2, { 0xF0, 0x6C, 0x00 } },
659
  { 0x50, 1, { 0x75, 0x00 }, 2, { 0xF0, 0x75, 0x00 } },
660
  { 0x51, 1, { 0x7D, 0x00 }, 2, { 0xF0, 0x7D, 0x00 } },
661
  { 0x56, 1, { 0x79, 0x00 }, 2, { 0xF0, 0x79, 0x00 } },
662
  { 0x53, 1, { 0x6B, 0x00 }, 2, { 0xF0, 0x6B, 0x00 } },
663
  { 0x54, 1, { 0x73, 0x00 }, 2, { 0xF0, 0x73, 0x00 } },
664
  { 0x55, 1, { 0x74, 0x00 }, 2, { 0xF0, 0x74, 0x00 } },
665
  { 0x57, 1, { 0x69, 0x00 }, 2, { 0xF0, 0x69, 0x00 } },
666
  { 0x58, 1, { 0x72, 0x00 }, 2, { 0xF0, 0x72, 0x00 } },
667
  { 0x59, 1, { 0x7A, 0x00 }, 2, { 0xF0, 0x7A, 0x00 } },
668
  { 0x6C, 2, { 0xE0, 0x5A }, 3, { 0xE0, 0xF0, 0x5A } },
669
  { 0x5A, 1, { 0x70, 0x00 }, 2, { 0xF0, 0x70, 0x00 } },
670
  { 0x5B, 1, { 0x71, 0x00 }, 2, { 0xF0, 0x71, 0x00 } },
671
};
672
 
673
 
674
static int keycodeCompare(const void *code1, const void *code2) {
675
  return ((Keycode *) code1)->xKeycode - ((Keycode *) code2)->xKeycode;
676
}
677
 
678
 
679
static void initKeycode(void) {
680
  qsort(kbdCodeTbl, sizeof(kbdCodeTbl)/sizeof(kbdCodeTbl[0]),
681
        sizeof(kbdCodeTbl[0]), keycodeCompare);
682
}
683
 
684
 
685
static Keycode *lookupKeycode(unsigned int xKeycode) {
686
  int lo, hi, tst;
687
  int res;
688
 
689
  lo = 0;
690
  hi = sizeof(kbdCodeTbl) / sizeof(kbdCodeTbl[0]) - 1;
691
  while (lo <= hi) {
692
    tst = (lo + hi) / 2;
693
    res = kbdCodeTbl[tst].xKeycode - xKeycode;
694
    if (res == 0) {
695
      return &kbdCodeTbl[tst];
696
    }
697
    if (res < 0) {
698
      lo = tst + 1;
699
    } else {
700
      hi = tst - 1;
701
    }
702
  }
703
  return NULL;
704
}
705
 
706
 
707
/**************************************************************/
708
 
709
 
710
#define KBD_BUF_MAX             100
711
#define KBD_BUF_NEXT(p)         (((p) + 1) % KBD_BUF_MAX)
712
 
713
 
714
static Byte kbdBuf[KBD_BUF_MAX];
715
static int kbdBufWritePtr;
716
static int kbdBufReadPtr;
717
 
718
 
719
static void kbdBufInit(void) {
720
  initKeycode();
721
  kbdBufWritePtr = 0;
722
  kbdBufReadPtr = 0;
723
}
724
 
725
 
726
static int kbdBufFree(void) {
727
  if (kbdBufReadPtr <= kbdBufWritePtr) {
728
    return KBD_BUF_MAX - (kbdBufWritePtr - kbdBufReadPtr) - 1;
729
  } else {
730
    return (kbdBufReadPtr - kbdBufWritePtr) - 1;
731
  }
732
}
733
 
734
 
735
static void keyPressed(unsigned int xKeycode) {
736
  Keycode *p;
737
  int i;
738
 
739
  if (debugKeycode) {
740
    cPrintf("**** KEY PRESSED: 0x%08X ****\n", xKeycode);
741
  }
742
  p = lookupKeycode(xKeycode);
743
  if (p == NULL) {
744
    /* keycode not found */
745
    return;
746
  }
747
  if (kbdBufFree() < (MAX_MAKE + MAX_BREAK) * 4) {
748
    /* buffer full */
749
    return;
750
  }
751
  for (i = 0; i < p->pcNumMake; i++) {
752
    kbdBuf[kbdBufWritePtr] = p->pcKeyMake[i];
753
    kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr);
754
  }
755
}
756
 
757
 
758
static void keyReleased(unsigned int xKeycode) {
759
  Keycode *p;
760
  int i;
761
 
762
  if (debugKeycode) {
763
    cPrintf("**** KEY RELEASED: 0x%08X ****\n", xKeycode);
764
  }
765
  p = lookupKeycode(xKeycode);
766
  if (p == NULL) {
767
    /* keycode not found */
768
    return;
769
  }
770
  if (kbdBufFree() < MAX_BREAK * 4) {
771
    /* buffer full */
772
    return;
773
  }
774
  for (i = 0; i < p->pcNumBreak; i++) {
775
    kbdBuf[kbdBufWritePtr] = p->pcKeyBreak[i];
776
    kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr);
777
  }
778
}
779
 
780
 
781
/**************************************************************/
782
 
783
 
784
static Word kbdCtrl;
785
static Word kbdData;
786
 
787
 
788
static void kbdCallback(int dev) {
789
  if (debug) {
790
    cPrintf("\n**** KEYBOARD CALLBACK ****\n");
791
  }
792 25 hellwig
  timerStart(KEYBOARD_USEC, kbdCallback, dev);
793 8 hellwig
  if (kbdBufWritePtr == kbdBufReadPtr) {
794
    /* no character ready */
795
    return;
796
  }
797
  /* any character typed */
798
  kbdData = kbdBuf[kbdBufReadPtr];
799
  kbdBufReadPtr = KBD_BUF_NEXT(kbdBufReadPtr);
800
  kbdCtrl |= KEYBOARD_RDY;
801
  if (kbdCtrl & KEYBOARD_IEN) {
802
    /* raise keyboard interrupt */
803
    cpuSetInterrupt(IRQ_KEYBOARD);
804
  }
805
}
806
 
807
 
808
Word keyboardRead(Word addr) {
809
  Word data;
810
 
811
  if (debug) {
812
    cPrintf("\n**** KEYBOARD READ from 0x%08X", addr);
813
  }
814
  if (!installed) {
815
    throwException(EXC_BUS_TIMEOUT);
816
  }
817
  if (addr == KEYBOARD_CTRL) {
818
    data = kbdCtrl;
819
  } else
820
  if (addr == KEYBOARD_DATA) {
821
    kbdCtrl &= ~KEYBOARD_RDY;
822
    if (kbdCtrl & KEYBOARD_IEN) {
823
      /* lower keyboard interrupt */
824
      cpuResetInterrupt(IRQ_KEYBOARD);
825
    }
826
    data = kbdData;
827
  } else {
828
    /* illegal register */
829
    throwException(EXC_BUS_TIMEOUT);
830
  }
831
  if (debug) {
832
    cPrintf(", data = 0x%08X ****\n", data);
833
  }
834
  return data;
835
}
836
 
837
 
838
void keyboardWrite(Word addr, Word data) {
839
  if (debug) {
840
    cPrintf("\n**** KEYBOARD WRITE to 0x%08X, data = 0x%08X ****\n",
841
            addr, data);
842
  }
843
  if (!installed) {
844
    throwException(EXC_BUS_TIMEOUT);
845
  }
846
  if (addr == KEYBOARD_CTRL) {
847
    if (data & KEYBOARD_IEN) {
848
      kbdCtrl |= KEYBOARD_IEN;
849
    } else {
850
      kbdCtrl &= ~KEYBOARD_IEN;
851
    }
852
    if (data & KEYBOARD_RDY) {
853
      kbdCtrl |= KEYBOARD_RDY;
854
    } else {
855
      kbdCtrl &= ~KEYBOARD_RDY;
856
    }
857
    if ((kbdCtrl & KEYBOARD_IEN) != 0 &&
858
        (kbdCtrl & KEYBOARD_RDY) != 0) {
859
      /* raise keyboard interrupt */
860
      cpuSetInterrupt(IRQ_KEYBOARD);
861
    } else {
862
      /* lower keyboard interrupt */
863
      cpuResetInterrupt(IRQ_KEYBOARD);
864
    }
865
  } else
866
  if (addr == KEYBOARD_DATA) {
867
    /* this register is read-only */
868
    throwException(EXC_BUS_TIMEOUT);
869
  } else {
870
    /* illegal register */
871
    throwException(EXC_BUS_TIMEOUT);
872
  }
873
}
874
 
875
 
876
void keyboardReset(void) {
877
  if (!installed) {
878
    return;
879
  }
880
  cPrintf("Resetting Keyboard...\n");
881
  kbdBufInit();
882
  kbdCtrl = 0;
883
  kbdData = 0;
884 25 hellwig
  timerStart(KEYBOARD_USEC, kbdCallback, 0);
885 8 hellwig
}
886
 
887
 
888
void keyboardInit(void) {
889
  if (!installed) {
890
    vgaInit();
891
  }
892
  keyboardReset();
893
}
894
 
895
 
896
void keyboardExit(void) {
897
  if (!installed) {
898
    return;
899
  }
900
  vgaExit();
901
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.