7 // Missing map entries for special keys, like F1..F12, Cursor up, etc.
8 char *keyboard_map
[256] = {
83 unsigned char keycode_fifo
[FIFO_SIZE
];
84 volatile uint64_t fifo_wp
= 0, fifo_rp
= 0;
87 interrupthandler(int id
)
90 unsigned keycode
= MMIX_IOSPACE
[MMIX_IO_KEYBOARD
];
91 MMIX_IOSPACE
[MMIX_IO_KEYBOARD
] = 0;
92 keycode_fifo
[fifo_wp
++] = keycode
;
93 fifo_wp
&= FIFO_SIZE
- 1;
94 MMIX_IOSPACE
[MMIX_IO_S7_0_OUT
] = ~fifo_wp
;
95 MMIX_IOSPACE
[MMIX_IO_S7_1_OUT
] = ~fifo_rp
;
100 static int kbRelease_on
= 0;
101 static int kbExtended_on
= 0;
102 static int kbCapsLock_on
= 0;
103 static int kbShift_on
= 0;
104 static int kbCtrl_on
= 0; // XXX Isn't really implemented yet
105 static int kbAlt_on
= 0; // XXX Isn't implemented yet
107 unsigned check_keyboard(void)
109 char *translation
, ch
= 0;
110 if (fifo_rp
!= fifo_wp
) {
112 unsigned keycode
= keycode_fifo
[fifo_rp
++];
113 fifo_rp
&= FIFO_SIZE
- 1;
115 if(D
)mmix_printf("keycode: %8x ", keycode
);
118 if(D
)mmix_printf("OVERFLOW: %16x ", keycode
);
120 //fb_puthex(2,keycode);
123 // Ctrl_R: E0 11 E0 F0 11
126 case 0xE0: kbExtended_on
= 1; break;
127 case 0xF0: kbRelease_on
= 1;
128 // fb_puts("RelOn ");
129 return 0; /* As to not clear extended */
130 case 0x58: kbCapsLock_on
^= !kbRelease_on
; break;
132 case 0x59: kbShift_on
= !kbRelease_on
;
135 fb_putchar(" o"[kbShift_on]);
136 fb_putchar(" R"[kbRelease_on]);
141 case 0x11: kbCtrl_on
= !kbRelease_on
; break;
145 fb_puthex(2,keycode);
147 fb_puthex(1,kbRelease_on);
149 fb_puthex(1,kbShift_on);
151 fb_puthex(1,kbExtended_on);
155 translation
= keyboard_map
[keycode
];
157 if (translation
&& !kbRelease_on
) {
158 //fb_putchar(translation[0]);
159 //fb_putchar(" o"[kbShift_on]);
163 if ((kbCapsLock_on
^ kbShift_on
) && translation
[1]) {
178 if(D
)mmix_printf("got %d\n", ch
);
182 char read_keyboard(void)
187 ch
= check_keyboard();
194 Key numbers: Tck: 30-50us, Tsu: 5-25us, Thld: 5-25us
197 // <parity> <b7> ... <b0>
198 void send_keyboard(long sh
, unsigned data_with_parity
)
200 unsigned long i
= -1;
202 #define set_data_clk(d,c) ({MMIX_IOSPACE[23] = (0xF & (((c) << 1) | (d)) << sh);})
203 #define get_data() ((MMIX_IOSPACE[23] >> sh) & 1)
204 #define get_clk() ((MMIX_IOSPACE[23] >> (sh+1)) & 1)
206 #define WAIT_UNTIL(cond) \
208 if (timeout <= now()){\
209 mmix_printf("\nTimed out waiting for " #cond " in line %d ", __LINE__); \
210 mmix_printf("(i == %d)", i); \
212 #define ms * (FREQUENCY / 1000)
214 unsigned long parity
= 1;
217 /* The device always generates the clock signal */
219 /* First, Request-to-Send */
221 set_data_clk(1,0); // Communication Inhibited
222 wait_us(100); // Wait at least 100 us
223 set_data_clk(0,0); // Bring the data line low
225 set_data_clk(0,1); // Host Request-to-Send (includes start bit)
227 timeout
= now() + 15 ms
;
229 // Wait for low clock
230 WAIT_UNTIL(get_clk() == 0);
232 timeout
= now() + 20 ms
;
234 for (i
= 1; i
<= 8; ++i
) {
237 set_data_clk(data_with_parity
& 1, 1);
238 parity
^= data_with_parity
& 1;
239 data_with_parity
>>= 1;
241 // Wait for clock to go high
242 WAIT_UNTIL(get_clk() == 1);
243 // Wait for low clock
244 WAIT_UNTIL(get_clk() == 0);
250 set_data_clk(parity
, 1);
252 WAIT_UNTIL(get_clk() == 1);
254 set_data_clk(1, 1); // Release the data line (9)
255 // Wait for data low (10)
257 WAIT_UNTIL(get_data() == 0);
258 // Wait for clock low (11)
259 WAIT_UNTIL(get_clk() == 0);
261 // Wait for release (12)
262 WAIT_UNTIL(get_clk() == 1 && get_data() == 1);
266 if (((MMIX_IOSPACE
[23] >> 1) & 1) != 0) {
267 mmix_printf("Keyboard didn't acknowledge!\n", 0);
269 mmix_printf("Done!\n", 0);
271 // Clear out cruft from buffer
272 // MMIX_IOSPACE[MMIX_IO_KEYBOARD] = 0;
276 extern void interruptvector(void);
280 long read_mouse_scancode(void)
282 long timeout
= now() + 20 ms
;
284 for (; now() < timeout
;)
285 if (fifo_rp
!= fifo_wp
) {
286 unsigned keycode
= keycode_fifo
[fifo_rp
++];
287 fifo_rp
&= FIFO_SIZE
- 1;
289 // if (keycode & 0xFF00)
290 // mmix_printf("Overflow? %4x ", keycode);
296 long x_pos
= 16 * 640 / 2;
297 long y_pos
= 16 * 480 / 2;
300 int check_mouse(void)
302 long buttons_and_more
;
303 long x_delta
, y_delta
;
305 buttons_and_more
= read_mouse_scancode();
306 if (buttons_and_more
< 0 || (~buttons_and_more
& 8)) {
307 if (buttons_and_more
!= -1)
308 mmix_printf("dropping <%4x> ", buttons_and_more
);
311 x_delta
= read_mouse_scancode();
313 //mmix_printf("timeout2 ", 0);
316 y_delta
= read_mouse_scancode();
318 //mmix_printf("timeout3 ", 0);
322 // buttons_and_more =
323 // Yoverflow Xoverflow Ysign Xsign 1 M_B R_B L_B
324 if (buttons_and_more
& 0x10) x_delta
= x_delta
- 256;
325 if (buttons_and_more
& 0x20) y_delta
= y_delta
- 256;
328 if (x_pos
< 0) x_pos
= 0;
329 else if (x_pos
>= 16 * 640) x_pos
= 16 * 640 - 1;
332 if (y_pos
< 0) y_pos
= 0;
333 else if (y_pos
>= 16 * 480) x_pos
= 16 * 480 - 1;
335 buttons
= buttons_and_more
& 7;
340 void undraw(uint64_t x
, uint64_t y
)
342 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
344 if (x
< 640 && y
< 480)
345 fb
[y
* 20 + (x
>> 5)] &= ~(0x80000000 >> (x
& 31));
348 void draw(uint64_t x
, uint64_t y
)
350 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
352 if (x
< 640 && y
< 480)
353 fb
[y
* 20 + (x
>> 5)] |= 0x80000000 >> (x
& 31);
356 void inline xdraw(uint64_t x
, uint64_t y
)
358 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
360 if (x
< 640 && y
< 480)
361 fb
[y
* 20 + (x
>> 5)] ^= 0x80000000 >> (x
& 31);
364 void xdraw_vline(uint64_t x
, uint64_t y
, int64_t len
)
366 static uint32_t * const fb
= (uint32_t *) (128 * 1024);
370 if (640 <= x
|| 480 <= y
|| len
<= 0)
376 p
= fb
+ 20 * y
+ (x
>> 5);
377 mask
= 0x80000000 >> (x
& 31);
380 case 3: *p
^= mask
, p
+= 20;
381 case 2: *p
^= mask
, p
+= 20;
382 case 1: *p
^= mask
, p
+= 20;
388 for (; len
; len
-= 4, p
+= 80) {
396 void xdraw_hline(uint64_t x
, uint64_t y
, int64_t len
)
398 static uint64_t * const fb
= (uint64_t *) (128 * 1024);
402 if (640 <= x
|| 480 <= y
|| len
<= 0)
407 p
= fb
+ 10 * y
+ (x
>> 6);
409 if ((x
& ~63) == ((x
+ len
- 1) & ~63)) {
410 // head & tail (special case for speed)
414 mask
= ~0UL >> (x
& 63);
417 mask
&= (1L << 63) >> ((x
+ len
- 1) & 63);
421 // | ___XXXXX | XXXXXXX | ... | XXXXXX | XXXXX___ |
425 *p
++ ^= ~0UL >> (x
& 63);
426 len
-= 64 - (x
& 63);
429 // | XXXXXX| ... | XXXXXX|
430 p_end
= p
+ (len
>> 6);
433 x
+= 64 * (len
>> 6);
434 len
-= 64 * (len
>> 6);
438 mask
= (1L << 63) >> ((x
+ len
- 1) & 63);
453 for (round
= 0; round
< 16; ++round
) {
454 for (n
= 1; n
< 256; ++n
) {
455 xdraw_hline(128-round
,round
+128+n
,n
);
459 mmix_printf("In test keyboard\n", 0);
461 //stdout = 1; // Frame buffer from here on
463 mmix_printf("Hello! Is this thing on? ", 0);
467 //mmix_printf("Enabling interrupts ", 0);
469 setInterruptVector((long)interruptvector
);
475 // Enable keyboard and mouse (0x00)
476 // Enable input (0x0F)
477 MMIX_IOSPACE
[MMIX_IO_KEYBOARD
] = 0;
478 MMIX_IOSPACE
[23] = 0x0F;
481 for (x_pos
= 30; x_pos
< 600; ++x_pos
) {
483 y_pos
+= (x_pos
& 10) ? 1 : -1;
486 #define check_kbd() ({\
487 if (fifo_rp != fifo_wp) { \
488 unsigned keycode = keycode_fifo[fifo_rp++]; \
489 fifo_rp &= FIFO_SIZE - 1; \
490 mmix_printf("%2x", keycode); }})
492 x_pos
= 16 * 640 / 2 ; y_pos
= 16 * 480 / 2;
494 xdraw_hline(0, y_pos
/ 16, 640);
495 xdraw_vline(x_pos
/ 16, 0, 480);
499 mmix_printf("\nready> ", 0);
501 long old_x
= x_pos
, old_y
= y_pos
;
504 if ( x_pos
/ 16 != old_x
/ 16
505 || y_pos
/ 16 != old_y
/ 16
508 xdraw_hline(0, old_y
/ 16, 640);
509 xdraw_vline(old_x
/ 16, 0, 480);
512 draw(x_pos
/ 16, y_pos
/ 16);
513 else if (buttons
& 2)
514 undraw(x_pos
/ 16, y_pos
/ 16);
517 xdraw_hline(0, y_pos
/ 16, 640);
518 xdraw_vline(x_pos
/ 16, 0, 480);
521 mmix_printf("(%d,", x_pos
);
522 mmix_printf("%d) ", y_pos
);
523 if (buttons
& 1) mmix_printf("L", 0);
524 if (buttons
& 2) mmix_printf("R", 0);
525 if (buttons
& 4) mmix_printf("M", 0);
526 mmix_printf(" \r", 0);
530 while (get_switches())
534 mmix_printf("Sending reset\n", 0);
535 send_keyboard(0, 0xFF);
536 read_mouse_scancode();
537 read_mouse_scancode();
539 send_keyboard(0, 0xFF);
540 read_mouse_scancode();
541 read_mouse_scancode();
543 send_keyboard(0, 0xF3);
544 send_keyboard(0, 200);
546 send_keyboard(0, 0xF3);
547 send_keyboard(0, 100);
549 send_keyboard(0, 0xF3);
550 send_keyboard(0, 50);
552 send_keyboard(0, 0xF2);
553 read_mouse_scancode();
555 send_keyboard(0, 0xF3);
556 send_keyboard(0, 10);
558 send_keyboard(0, 0xE8);
561 send_keyboard(0, 0xE6);
563 send_keyboard(0, 0xF3);
564 send_keyboard(0, 40);
566 send_keyboard(0, 0xF4);
568 /* mmix_printf("Flashing LEDs\n", 0);
569 for (sw = 200; --sw;) {
570 send_keyboard(0, 0xED);
571 send_keyboard(0, led);
573 led = (led == 4) ? 1 : led << 1;
579 draw(x_pos
+ 1, y_pos
);
580 draw(x_pos
- 1, y_pos
);
581 draw(x_pos
, y_pos
+ 1);
582 draw(x_pos
, y_pos
- 1);
586 mmix_printf("Mouse on\n", 0);
587 send_keyboard(0, 0xF6);
592 char ch
= read_keyboard();
594 mmix_printf("Ok, as you wish. Launching test\n", 0);
596 send_keyboard(0xFF + 0x100); // Reset
597 } else if (ch
== 's') {
598 send_keyboard(0xED + 0x100);
599 send_keyboard(0x02 + 0x000);
600 } else if (ch
== 'c') {
602 } else if (ch
!= '\b' || stdout
== 0)
605 fb_gotoxy(fb_io_x
-1,fb_io_y
);
607 fb_gotoxy(fb_io_x
-1,fb_io_y
);