/[mit-cadr]/branches/ggilley/emulator/usim/iob.c
ViewVC logotype

Contents of /branches/ggilley/emulator/usim/iob.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 410 - (show annotations)
Sun Mar 3 22:44:10 2013 UTC (13 months, 2 weeks ago) by ggilley
File MIME type: text/plain
File size: 9749 byte(s)
fix an error and some warnings
1 /*
2 * iob.c
3 *
4 * simple CADR i/o board simulation
5 * support for mouse, keyboard, clock
6 *
7 * $Id$
8 */
9
10 #include "usim.h"
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdint.h>
15 #include <signal.h>
16
17 #if defined(LINUX) || defined(OSX) || defined(BSD)
18 #include <sys/time.h>
19 #endif
20
21 #ifdef DISPLAY_SDL
22 #ifdef _WIN32
23 #include <SDL/SDL_keysym.h>
24 #else
25 #include "SDL/SDL_keysym.h"
26 #endif
27 #endif /* DISPLAY_SDL */
28
29 #include "ucode.h"
30 #include "chaos.h"
31
32 unsigned int iob_key_scan;
33 unsigned int iob_kbd_csr;
34
35 int mouse_x, mouse_y;
36 int mouse_head, mouse_middle, mouse_tail;
37 int mouse_rawx, mouse_rawy;
38 int mouse_poll_delay;
39
40 /* location in A memory of micrcode mouse state */
41 static int mouse_sync_amem_x;
42 static int mouse_sync_amem_y;
43
44 extern int mouse_sync_flag;
45 extern int get_u_pc();
46 extern unsigned int read_a_mem(int loc);
47 extern int sym_find(int mcr, char *name, int *pval);
48
49 void tv_post_60hz_interrupt(void);
50 void chaos_xmit_pkt(void);
51
52 /*
53 CADR i/o board
54
55 interrupt vectors:
56 260 kdb/mouse
57 264 serial
58 270 chaos int
59 274 clock
60 400 ether xmit done
61 404 ether rcv done
62 410 ether collision
63
64 764100
65 0 0 read kbd
66 2 1 read kbd
67 4 2 read mouse y (12 bits)
68 6 3 read mouse x (12 bits)
69 10 4 click audio
70 12 5 kbd/mouse csr
71
72 csr - write
73 0 remote mouse enable
74 1 mouse int enable
75 2 kbd int enable
76 3 clock int enable
77
78 csr - read
79 0 remote mouse eable
80 1 mouse int enable
81 2 kbd int enable
82 3 clock int enable
83 4 mouse ready
84 5 kbd ready
85 6 clock ready
86 7 ser int enable
87
88 keyboard
89 ; 5-0 keycode
90 ; 7-6 shift
91 ; 9-8 top
92 ; 11-10 control
93 ; 13-12 meta
94 ; 14 shift-lock
95 ; 15 unused
96
97 */
98
99 /*
100 764100
101 0 read kbd
102 1 read kbd
103 2 read mouse y (12 bits)
104 3 read mouse x (12 bits)
105 4 click audio
106 5 kbd/mouse csr
107
108 csr - write
109 0 remote mouse enable
110 1 mouse int enable
111 2 kbd int enable
112 3 clock int enable
113
114 csr - read
115 0 remote mouse eable
116 1 mouse int enable
117 2 kbd int enable
118 3 clock int enable
119 4 mouse ready
120 5 kbd ready
121 6 clock ready
122 7 ser int enable
123 */
124
125 #define US_CLOCK_IS_WALL_CLOCK
126 #if defined(linux) || defined(osx)
127 #define USE_SIGVTARLM_FOR_60HZ
128 #endif
129
130 #ifdef _WIN32
131 #define USE_US_CLOCK_FOR_60HZ
132 #endif
133
134 unsigned long
135 get_us_clock()
136 {
137 unsigned long v;
138 #ifdef US_CLOCK_IS_WALL_CLOCK
139 static unsigned long last_hz60;
140 static struct timeval tv;
141 struct timeval tv2;
142 unsigned long ds, du;
143
144 if (tv.tv_sec == 0) {
145 gettimeofday(&tv, 0);
146 v = 0;
147 last_hz60 = 0;
148 } else {
149 gettimeofday(&tv2, 0);
150
151 if (tv2.tv_usec < tv.tv_usec) {
152 tv2.tv_sec--;
153 tv2.tv_usec += 1000*1000;
154 }
155 ds = tv2.tv_sec - tv.tv_sec;
156 du = tv2.tv_usec - tv.tv_usec;
157
158 // v = (ds * 100) + (du / 10000);
159 v = (ds * 1000*1000) + du;
160 if (0) printf("delta %lu\n", v);
161
162 #ifdef USE_US_CLOCK_FOR_60HZ
163 hz60 = v / 16000;
164 if (hz60 > last_hz60) {
165 last_hz60 = hz60;
166 tv_post_60hz_interrupt();
167 }
168 #endif
169 }
170 #else
171 /* assume 200ns cycle, we want 1us */
172 extern long cycles;
173 v = cycles * (1000/200);
174 #endif
175
176 return v;
177 }
178
179 static unsigned long cv;
180
181 unsigned int
182 get_us_clock_low(void)
183 {
184 cv = get_us_clock();
185 return cv & 0xffff;
186 }
187
188 unsigned int
189 get_us_clock_high(void)
190 {
191 return (unsigned int)(cv >> 16);
192 }
193
194 unsigned int get_60hz_clock(void)
195 {
196 return 0;
197 }
198
199
200 void
201 iob_unibus_read(int offset, int *pv)
202 {
203 /* default, for now */
204 *pv = 0;
205
206 switch (offset) {
207 case 0100:
208 *pv = iob_key_scan & 0177777;
209 traceio("unibus: kbd low %011o\n", *pv);
210 iob_kbd_csr &= ~(1 << 5);
211 break;
212 case 0102:
213 *pv = (iob_key_scan >> 16) & 0177777;
214 iob_kbd_csr &= ~(1 << 5);
215 traceio("unibus: kbd high %011o\n", *pv);
216 break;
217 case 0104:
218 traceio("unibus: mouse y\n");
219 *pv = (mouse_tail << 12) |
220 (mouse_middle << 13) |
221 (mouse_head << 14) |
222 (mouse_y & 07777);
223
224 mouse_tail = 0;
225 mouse_middle = 0;
226 mouse_head = 0;
227
228 iob_kbd_csr &= ~(1 << 4);
229 break;
230 case 0106:
231 traceio("unibus: mouse x\n");
232 *pv = (mouse_rawx << 12) | (mouse_rawy << 14) |
233 (mouse_x & 07777);
234 break;
235 case 0110:
236 traceio("unibus: beep\n");
237 fprintf(stderr,"\a"); /* alert - beep */
238 break;
239 case 0112:
240 *pv = iob_kbd_csr;
241 traceio("unibus: kbd csr %011o\n", *pv);
242 break;
243 case 0120:
244 traceio("unibus: usec clock low\n");
245 *pv = get_us_clock_low();
246 break;
247 case 0122:
248 traceio("unibus: usec clock high\n");
249 *pv = get_us_clock_high();
250 break;
251 case 0124:
252 printf("unibus: 60hz clock\n");
253 *pv = get_60hz_clock();
254 break;
255 case 0140:
256 //tracenet("unibus: chaos read\n");
257 *pv = chaos_get_csr();
258 break;
259 case 0142:
260 tracenet("unibus: chaos read my-number\n");
261 *pv = chaos_get_addr();
262 break;
263 case 0144:
264 *pv = chaos_get_rcv_buffer();
265 tracenet("unibus: chaos read rcv buffer %06o\n", *pv);
266 break;
267 case 0146:
268 *pv = chaos_get_bit_count();
269 tracenet("unibus: chaos read bit-count 0%o\n", *pv);
270 break;
271 case 0152:
272 *pv = chaos_get_addr();
273 tracenet("unibus: chaos read xmt => %o\n", *pv);
274 chaos_xmit_pkt();
275 break;
276 default:
277 if (offset > 0140 && offset <= 0153)
278 printf/*traceio*/("unibus: chaos read other %o\n",
279 offset);
280 chaos_xmit_pkt();
281 break;
282 }
283 }
284
285 void
286 iob_unibus_write(int offset, int v)
287 {
288 switch (offset) {
289 case 0100:
290 traceio("unibus: kbd low\n");
291 break;
292 case 0102:
293 traceio("unibus: kbd high\n");
294 break;
295 case 0104:
296 traceio("unibus: mouse y\n");
297 break;
298 case 0106:
299 traceio("unibus: mouse x\n");
300 break;
301 case 0110:
302 traceio("unibus: beep\n");
303 break;
304 case 0112:
305 traceio("unibus: kbd csr\n");
306 iob_kbd_csr =
307 (iob_kbd_csr & ~017) | (v & 017);
308 break;
309 case 0120:
310 traceio("unibus: usec clock\n");
311 break;
312 case 0122:
313 traceio("unibus: usec clock\n");
314 break;
315 case 0124:
316 printf("unibus: START 60hz clock\n");
317 break;
318 case 0140:
319 traceio("unibus: chaos write %011o, u_pc %011o ",
320 v, get_u_pc());
321 #ifdef CHAOS_DEBUG
322 show_label_closest(get_u_pc());
323 printf("\n");
324 #endif
325 chaos_set_csr(v);
326 break;
327 case 0142:
328 traceio("unibus: chaos write-buffer write %011o, u_pc %011o\n",
329 v, get_u_pc());
330 chaos_put_xmit_buffer(v);
331 break;
332 default:
333 if (offset > 0140 && offset <= 0152)
334 printf/*traceio*/("unibus: chaos write other\n");
335 break;
336 }
337 }
338
339 void
340 iob_sdl_mouse_event(int x, int y, int dx, int dy, int buttons)
341 {
342 iob_kbd_csr |= 1 << 4;
343 assert_unibus_interrupt(0264);
344
345 #if 0
346 printf("iob_sdl_mouse_event(dx=%x,dy=%x,buttons=%x) x %o, y %o\n",
347 dx, dy, buttons, mouse_x, mouse_y);
348 mouse_x += dx;
349 mouse_y += dy;
350 #endif
351
352 if (0)
353 printf("iob_sdl_mouse_event(x=%x,y=%x,buttons=%x)\n",
354 x, y, buttons);
355
356 if (mouse_sync_flag) {
357 int mcx, mcy, dx, dy;
358
359 /* move mouse closer to where microcode thinks it is */
360 mcx = read_a_mem(mouse_sync_amem_x);
361 mcy = read_a_mem(mouse_sync_amem_y);
362
363 dx = x - mcx;
364 dy = y - mcy;
365
366 //printf("m %d,%d mc %d,%d c %d,%d d %d,%d\n",
367 //mouse_x, mouse_y, mcx, mcy, x, y, dx, dy);
368
369 mouse_x += dx;
370 mouse_y += dy;
371 } else {
372 /* convert SDL coods in to mouse loc */
373 mouse_x = (x*4)/3;
374 mouse_y = (y*5)/3;
375 }
376
377 if (buttons & 4)
378 mouse_head = 1;
379 if (buttons & 2)
380 mouse_middle = 1;
381 if (buttons & 1)
382 mouse_tail = 1;
383 }
384
385 /*
386 * create simulated mouse motion to keep SDL cursor
387 * and microcode cursor in sync
388 */
389 void
390 iob_sdl_mouse_poll(int x, int y)
391 {
392 int mcx, mcy, dx, dy;
393
394 if (iob_kbd_csr & (1 << 4))
395 return;
396
397 mcx = read_a_mem(mouse_sync_amem_x);
398 mcy = read_a_mem(mouse_sync_amem_y);
399
400 if (mcx == 0 && mcy == 0)
401 return;
402
403 dx = x - mcx;
404 dy = y - mcy;
405
406 #define MAX_MOTION 5
407 #define POLL_DELAY 20
408
409 if (dx || dy) {
410
411 if (mouse_poll_delay) {
412 mouse_poll_delay--;
413 if (mouse_poll_delay > 0)
414 return;
415 }
416
417 if (dx > MAX_MOTION)
418 dx = MAX_MOTION;
419 if (dy > MAX_MOTION)
420 dy = MAX_MOTION;
421
422 mouse_x += dx;
423 mouse_y += dy;
424
425 //printf("P: m %d,%d mc %d,%d c %d,%d d %d,%d\n",
426 //mouse_x, mouse_y, mcx, mcy, x, y, dx, dy);
427
428 iob_kbd_csr |= 1 << 4;
429 assert_unibus_interrupt(0264);
430
431 mouse_poll_delay = POLL_DELAY;
432 }
433 }
434
435
436 int tv_csr;
437
438 int
439 tv_xbus_read(int offset, unsigned int *pv)
440 {
441 if (0) printf("tv register read, offset %o -> %o\n", offset, tv_csr);
442 *pv = tv_csr;
443 return 0;
444 }
445
446 int
447 tv_xbus_write(int offset, unsigned int v)
448 {
449 if (0) printf("tv register write, offset %o, v %o\n", offset, v);
450 if ((tv_csr & 4) != (v & 4)) {
451 #ifdef DISPLAY_SDL
452 sdl_set_bow_mode((v & 4)>>2);
453 #endif
454 }
455 tv_csr = v;
456 tv_csr &= ~(1 << 4);
457 deassert_xbus_interrupt();
458 return 0;
459 }
460
461 //xxx tv interrupt
462 // tv csr @ base, 1<<4 = interrupt flag
463 // writing back clears int
464 // 60hz
465
466 void
467 tv_post_60hz_interrupt(void)
468 {
469 tv_csr |= 1 << 4;
470 assert_xbus_interrupt();
471 }
472
473 void
474 iob_sdl_clock_event()
475 {
476 iob_kbd_csr |= 1 << 6;
477 assert_unibus_interrupt(0274);
478 }
479
480 void
481 sigalrm_handler(int arg)
482 {
483 if (0) printf("sigalrm_handler()\n");
484 tv_post_60hz_interrupt();
485 }
486
487 void
488 iob_poll(unsigned long cycles)
489 {
490 #ifndef USE_SIGVTARLM_FOR_60HZ
491 /* assume 200ns cycle, we want 16ms */
492 if ((cycles % ((16*1000*1000)/200)) == 0) {
493 tv_post_60hz_interrupt();
494 }
495 #endif
496 }
497
498 void
499 mouse_sync_init(void)
500 {
501 int val;
502
503 //A-MOUSE-CURSOR-X A-MEM 516
504 //A-MOUSE-CURSOR-Y A-MEM 517
505
506 mouse_sync_amem_x = 334;
507 mouse_sync_amem_y = 335;
508
509 if (sym_find(1, "A-MOUSE-CURSOR-X", &val)) {
510 printf("can't find A-MOUSE-CURSOR-X in microcode symbols\n");
511 } else
512 mouse_sync_amem_x = val;
513
514 if (sym_find(1, "A-MOUSE-CURSOR-Y", &val)) {
515 printf("can't find A-MOUSE-CURSOR-Y in microcode symbols\n");
516 } else
517 mouse_sync_amem_y = val;
518
519 if (0)
520 printf("mouse_sync_amem_x %o, mouse_sync_amem_y %o\n",
521 mouse_sync_amem_x, mouse_sync_amem_y);
522 }
523
524 int
525 iob_init(void)
526 {
527 kbd_init();
528
529 if (mouse_sync_flag) {
530 mouse_sync_init();
531 }
532
533 #ifdef USE_SIGVTARLM_FOR_60HZ
534 {
535 struct itimerval itimer;
536 int usecs;
537
538 signal(SIGVTALRM, sigalrm_handler);
539
540 usecs = 16000;
541
542 itimer.it_interval.tv_sec = 0;
543 itimer.it_interval.tv_usec = usecs;
544 itimer.it_value.tv_sec = 0;
545 itimer.it_value.tv_usec = usecs;
546 setitimer(ITIMER_VIRTUAL, &itimer, 0);
547 }
548 #endif
549
550 return 0;
551 }
552

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5