6 #include "../audio/newgame-sound.c"
8 unsigned char *next_sample
;
9 unsigned char *stop_sound
;
16 // Missing map entries for special keys, like F1..F12, Cursor up, etc.
17 char *keyboard_map
[256] = {
92 unsigned char keycode_fifo
[FIFO_SIZE
], mousecode_fifo
[FIFO_SIZE
];
93 volatile uint64_t kfifo_wp
= 0, kfifo_rp
= 0, mfifo_wp
= 0, mfifo_rp
= 0;
96 interrupthandler(int id
)
99 setInterval(FREQUENCY
/ 11250 - 100);
101 if (next_sample
!= stop_sound
) {
102 DAC_both
= *next_sample
++ << 8;
104 } else if (id
== 40) {
105 unsigned keycode
= MMIX_IOSPACE
[MMIX_IO_KEYBOARD
];
106 MMIX_IOSPACE
[MMIX_IO_KEYBOARD
] = 0;
107 keycode_fifo
[kfifo_wp
++] = keycode
;
108 kfifo_wp
&= FIFO_SIZE
- 1;
109 MMIX_IOSPACE
[MMIX_IO_S7_0_OUT
] = ~kfifo_wp
;
110 MMIX_IOSPACE
[MMIX_IO_S7_1_OUT
] = ~kfifo_rp
;
111 } else if (id
== 41) {
112 unsigned mousecode
= MMIX_IOSPACE
[MMIX_IO_MOUSE
];
113 MMIX_IOSPACE
[MMIX_IO_MOUSE
] = 0;
114 mousecode_fifo
[mfifo_wp
++] = mousecode
;
115 mfifo_wp
&= FIFO_SIZE
- 1;
116 MMIX_IOSPACE
[MMIX_IO_S7_0_OUT
] = ~mfifo_wp
;
117 MMIX_IOSPACE
[MMIX_IO_S7_1_OUT
] = ~mfifo_rp
;
122 static int kbRelease_on
= 0;
123 static int kbExtended_on
= 0;
124 static int kbCapsLock_on
= 0;
125 static int kbShift_on
= 0;
126 static int kbCtrl_on
= 0; // XXX Isn't really implemented yet
127 static int kbAlt_on
= 0; // XXX Isn't implemented yet
129 unsigned check_keyboard(void)
131 char *translation
, ch
= 0;
132 if (kfifo_rp
!= kfifo_wp
) {
134 unsigned keycode
= keycode_fifo
[kfifo_rp
++];
135 kfifo_rp
&= FIFO_SIZE
- 1;
137 if(D
)mmix_printf("keycode: %8x ", keycode
);
140 if(D
)mmix_printf("OVERFLOW: %16x ", keycode
);
142 //fb_puthex(2,keycode);
145 // Ctrl_R: E0 11 E0 F0 11
148 case 0xE0: kbExtended_on
= 1; break;
149 case 0xF0: kbRelease_on
= 1;
150 // fb_puts("RelOn ");
151 return 0; /* As to not clear extended */
152 case 0x58: kbCapsLock_on
^= !kbRelease_on
; break;
154 case 0x59: kbShift_on
= !kbRelease_on
;
157 fb_putchar(" o"[kbShift_on]);
158 fb_putchar(" R"[kbRelease_on]);
163 case 0x11: kbCtrl_on
= !kbRelease_on
; break;
167 fb_puthex(2,keycode);
169 fb_puthex(1,kbRelease_on);
171 fb_puthex(1,kbShift_on);
173 fb_puthex(1,kbExtended_on);
177 translation
= keyboard_map
[keycode
];
179 if (translation
&& !kbRelease_on
) {
180 //fb_putchar(translation[0]);
181 //fb_putchar(" o"[kbShift_on]);
185 if ((kbCapsLock_on
^ kbShift_on
) && translation
[1]) {
200 if(D
)mmix_printf("got %d\n", ch
);
204 char read_keyboard(void)
209 ch
= check_keyboard();
216 Key numbers: Tck: 30-50us, Tsu: 5-25us, Thld: 5-25us
219 // <parity> <b7> ... <b0>
220 void send_ps2(unsigned sh
, unsigned data_with_parity
)
222 unsigned long i
= -1;
224 #define set_data_clk(d,c) ({MMIX_IOSPACE[MMIX_IO_PS2_RAW] = 0xF & (((c << 1) | (d)) << sh);})
225 #define get_data() ((MMIX_IOSPACE[MMIX_IO_PS2_RAW] >> sh) & 1)
226 #define get_clk() ((MMIX_IOSPACE[MMIX_IO_PS2_RAW] >> (sh+1)) & 1)
228 #define WAIT_UNTIL(cond) \
230 if (timeout <= now()){\
231 mmix_printf("\nTimed out waiting for " #cond " in line %d ", __LINE__); \
232 mmix_printf("(i == %d)", i); \
234 #define ms * (FREQUENCY / 1000)
236 unsigned long parity
= 1;
239 /* The device always generates the clock signal */
241 /* First, Request-to-Send */
243 set_data_clk(1,0); // Communication Inhibited
244 wait_us(100); // Wait at least 100 us
245 set_data_clk(0,0); // Bring the data line low
247 set_data_clk(0,1); // Host Request-to-Send (includes start bit)
249 timeout
= now() + 15 ms
;
251 // Wait for low clock
252 WAIT_UNTIL(get_clk() == 0);
254 timeout
= now() + 20 ms
;
256 for (i
= 1; i
<= 8; ++i
) {
259 set_data_clk(data_with_parity
& 1, 1);
260 parity
^= data_with_parity
& 1;
261 data_with_parity
>>= 1;
263 // Wait for clock to go high
264 WAIT_UNTIL(get_clk() == 1);
265 // Wait for low clock
266 WAIT_UNTIL(get_clk() == 0);
272 set_data_clk(parity
, 1);
274 WAIT_UNTIL(get_clk() == 1);
276 set_data_clk(1, 1); // Release the data line (9)
277 // Wait for data low (10)
279 WAIT_UNTIL(get_data() == 0);
280 // Wait for clock low (11)
281 WAIT_UNTIL(get_clk() == 0);
283 // Wait for release (12)
284 WAIT_UNTIL(get_clk() == 1 && get_data() == 1);
288 if (((MMIX_IOSPACE
[MMIX_IO_PS2_RAW
] >> 1) & 1) != 0) {
289 mmix_printf("Keyboard didn't acknowledge!\n", 0);
291 mmix_printf("Done!\n", 0);
293 // Clear out cruft from buffer
294 // MMIX_IOSPACE[MMIX_IO_KEYBOARD] = 0;
298 void send_keyboard(unsigned data
) {send_ps2(0, data
);}
299 void send_mouse(unsigned data
) {send_ps2(2, data
);}
301 extern void interruptvector(void);
305 long read_mouse_scancode(long wait
)
307 long timeout
= now() + wait
;
309 for (; now() < timeout
;)
310 if (mfifo_rp
!= mfifo_wp
) {
311 unsigned mousecode
= mousecode_fifo
[mfifo_rp
++];
312 mfifo_rp
&= FIFO_SIZE
- 1;
314 if (mousecode
& 0xFF00)
315 mmix_printf("Overflow? %4x ", mousecode
);
321 long x_pos
= 16 * 640 / 2;
322 long y_pos
= 16 * 480 / 2;
325 int check_mouse(void)
327 long buttons_and_more
;
328 long x_delta
, y_delta
;
330 buttons_and_more
= read_mouse_scancode(30 ms
);
331 if (buttons_and_more
< 0 || (~buttons_and_more
& 8)) {
332 if (buttons_and_more
!= -1)
333 fb_cursor_off(), mmix_printf("dropping <%4x> ", buttons_and_more
),
337 x_delta
= read_mouse_scancode(100 ms
);
339 //mmix_printf("timeout2 ", 0);
342 y_delta
= read_mouse_scancode(100 ms
);
344 //mmix_printf("timeout3 ", 0);
348 // buttons_and_more =
349 // Yoverflow Xoverflow Ysign Xsign 1 M_B R_B L_B
350 if (buttons_and_more
& 0x10) x_delta
= x_delta
- 256;
351 if (buttons_and_more
& 0x20) y_delta
= y_delta
- 256;
354 if (x_pos
< 0) x_pos
= 0;
355 else if (x_pos
>= 16 * 640) x_pos
= 16 * 640 - 1;
358 if (y_pos
< 0) y_pos
= 0;
359 else if (y_pos
>= 16 * 480) y_pos
= 16 * 480 - 1;
361 buttons
= buttons_and_more
& 7;
366 void service_keyboard(void)
368 char ch
= check_keyboard();
371 if (ch
== 8 && fb_io_x
) {
381 void undraw(uint64_t x
, uint64_t y
)
383 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
385 if (x
< 640 && y
< 480)
386 fb
[y
* 20 + (x
>> 5)] &= ~(0x80000000 >> (x
& 31));
389 void draw(uint64_t x
, uint64_t y
)
391 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
393 if (x
< 640 && y
< 480)
394 fb
[y
* 20 + (x
>> 5)] |= 0x80000000 >> (x
& 31);
397 void inline xdraw(uint64_t x
, uint64_t y
)
399 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
401 if (x
< 640 && y
< 480)
402 fb
[y
* 20 + (x
>> 5)] ^= 0x80000000 >> (x
& 31);
405 void xdraw_vline(uint64_t x
, uint64_t y
, int64_t len
)
407 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
411 if (640 <= x
|| 480 <= y
|| len
<= 0)
417 p
= fb
+ 20 * y
+ (x
>> 5);
418 mask
= 0x80000000 >> (x
& 31);
421 case 3: *p
^= mask
, p
+= 20;
422 case 2: *p
^= mask
, p
+= 20;
423 case 1: *p
^= mask
, p
+= 20;
429 for (; len
; len
-= 4, p
+= 80) {
437 void xdraw_hline(uint64_t x
, uint64_t y
, int64_t len
)
439 static uint64_t * const fb
= (uint64_t *) (128 * 1024);
443 if (640 <= x
|| 480 <= y
|| len
<= 0)
448 p
= fb
+ 10 * y
+ (x
>> 6);
450 if ((x
& ~63) == ((x
+ len
- 1) & ~63)) {
451 // head & tail (special case for speed)
455 mask
= ~0UL >> (x
& 63);
458 mask
&= (1L << 63) >> ((x
+ len
- 1) & 63);
462 // | ___XXXXX | XXXXXXX | ... | XXXXXX | XXXXX___ |
466 *p
++ ^= ~0UL >> (x
& 63);
467 len
-= 64 - (x
& 63);
470 // | XXXXXX| ... | XXXXXX|
471 p_end
= p
+ (len
>> 6);
474 x
+= 64 * (len
>> 6);
475 len
-= 64 * (len
>> 6);
479 mask
= (1L << 63) >> ((x
+ len
- 1) & 63);
486 void play(unsigned char *sound
, unsigned length
)
489 stop_sound
= sound
+ length
;
492 void xdraw_mouse(unsigned long x_pos
, unsigned long y_pos
)
494 xdraw_hline(x_pos
/16-10, y_pos
/16, 20);
495 xdraw_vline(x_pos
/16, y_pos
/16-10, 20);
508 for (round
= 0; round
< 16; ++round
) {
509 for (n
= 1; n
< 256; ++n
) {
510 xdraw_hline(128-round
,round
+128+n
,n
);
514 mmix_printf("In test keyboard\n", 0);
516 stdout
= 1; // Frame buffer from here on
518 mmix_printf("Hello! Is this thing on? ", 0);
522 //mmix_printf("Enabling interrupts ", 0);
524 setInterruptVector((long)interruptvector
);
530 play(blob
, sizeof(blob
));
532 // Enable keyboard and mouse (0x00)
533 // Enable input (0x0F)
534 MMIX_IOSPACE
[MMIX_IO_KEYBOARD
] = 0;
535 MMIX_IOSPACE
[MMIX_IO_MOUSE
] = 0;
536 MMIX_IOSPACE
[MMIX_IO_PS2_RAW
] = 0x0F;
539 for (x_pos
= 30; x_pos
< 600; ++x_pos
) {
541 y_pos
+= (x_pos
& 10) ? 1 : -1;
544 x_pos
= 16 * 640 / 2 ; y_pos
= 16 * 480 / 2;
546 // xdraw_hline(0, y_pos / 16, 640);
547 // xdraw_vline(x_pos / 16, 0, 480);
554 xdraw_mouse(x_pos
, y_pos
);
557 long old_x
= x_pos
, old_y
= y_pos
;
561 if ((buttons
& 2) && x_pos
== 0 && y_pos
== 0)
562 play(blob
, sizeof(blob
));
564 if ( x_pos
/ 16 != old_x
/ 16
565 || y_pos
/ 16 != old_y
/ 16
568 xdraw_mouse(old_x
, old_y
);
571 draw(x_pos
/16, y_pos
/16);
572 else if (buttons
& 2)
573 undraw(x_pos
/16, y_pos
/16);
576 xdraw_mouse(x_pos
, y_pos
);
581 xdraw_mouse(x_pos
, y_pos
);
583 while (get_switches());
586 mmix_printf("Sending reset\n", 0);
588 read_mouse_scancode(10 ms
);
589 read_mouse_scancode(10 ms
);
592 read_mouse_scancode(10 ms
);
593 read_mouse_scancode(10 ms
);
605 read_mouse_scancode(10 ms
);
622 mmix_printf("Flashing LEDs\n", 0);
624 for (sw
= 20; --sw
;) {
629 led
= (led
== 4) ? 1 : led
<< 1;
635 draw(x_pos
+ 1, y_pos
);
636 draw(x_pos
- 1, y_pos
);
637 draw(x_pos
, y_pos
+ 1);
638 draw(x_pos
, y_pos
- 1);
639 play(blob
, sizeof(blob
));
645 mmix_printf("Mouse on\n", 0);