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

Subversion Repositories eco32

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

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

powered by: WebSVN 2.1.0

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