OSDN Git Service

[VM][FM7][KEYBOARD] Fix don't do auto-repeat at FM-7/77 .
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / keyboard.cpp
1 /*
2  * Common Source code Project -> VM -> FM-7/77AV -> Keyboard
3  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  * Licence: GPLv2
5  * History : 
6  *  Feb 12, 2015 : Initial 
7  */
8
9 #include "../../fifo.h"
10 #include "../device.h"
11 #include "fm7_keyboard.h"
12
13 #include "keyboard_tables.h"
14 #if defined(_FM77AV_VARIANTS)
15 #include "../beep.h"
16 #include "fm77av_hidden_message_keyboard.h"
17 #endif
18 enum {
19         ID_KEYBOARD_RXRDY_OK = 1,
20         ID_KEYBOARD_ACK,
21         ID_KEYBOARD_RXRDY_BUSY,
22         ID_KEYBOARD_RTC_COUNTUP,
23         ID_KEYBOARD_INT,
24         ID_KEYBOARD_AUTOREPEAT_FIRST,
25         ID_KEYBOARD_AUTOREPEAT,
26         ID_KEYBOARD_HIDDENMESSAGE_AV,
27         ID_KEYBOARD_HIDDEN_BEEP_ON,
28         ID_KEYBOARD_HIDDEN_BEEP_OFF,
29 };
30
31 //
32 /*
33  * I/O API (subio)
34  */
35 // 0xd400(SUB) or 0xfd00(MAIN)
36 uint8 KEYBOARD::get_keycode_high(void)
37 {
38         uint8 data = 0x00;
39         if((keycode_7 & 0x0100) != 0) data = 0x80;
40         return data;
41 }
42
43 // 0xd401(SUB) or 0xfd01(MAIN)
44 uint8 KEYBOARD::get_keycode_low(void)
45 {
46         uint8 data = keycode_7 & 0xff;
47         this->write_signals(&int_line, 0x00000000);
48         return data;
49 }
50
51 // 0xd40d : R
52 void KEYBOARD::turn_on_ins_led(void)
53 {
54         this->write_signals(&ins_led, 0xff);
55 }
56
57 // 0xd40d : W
58 void KEYBOARD::turn_off_ins_led(void)
59 {
60         this->write_signals(&ins_led, 0x00);
61 }
62
63 // UI Handler. 
64 uint16 KEYBOARD::vk2scancode(uint32 vk)
65 {
66         uint16 i;
67         i = 0;
68         if(vk == VK_PAUSE) vk = VK_KANJI; // Workaround some desktop environments for [ESC].
69         do {
70                 if(vk_matrix_106[i] == vk) return i;
71                 i++;
72         } while(vk_matrix_106[i] != 0xffff);
73         return 0x0000;
74 }
75
76 bool KEYBOARD::isModifier(uint16 sc)
77 {
78         if(((sc >= 0x52) && (sc <= 0x56)) || // CTRL LSHIFT RSHIFT CAPS GRPH
79                 (sc == 0x5a) || (sc == 0x5c)) { // KANA BREAK
80                 return true;
81         }
82         return false;
83 }
84
85 void KEYBOARD::set_modifiers(uint16 sc, bool flag)
86 {
87         if(sc == 0x52) { // CTRL
88                 ctrl_pressed = flag; 
89         } else if(sc == 0x53) { // LSHIFT
90                 lshift_pressed = flag;
91                 shift_pressed = lshift_pressed | rshift_pressed;
92                 //printf("LSHIFT : %d\n", flag ? 1 : 0);
93         } else if(sc == 0x54) { // RSHIFT
94                 rshift_pressed = flag;
95                 shift_pressed = lshift_pressed | rshift_pressed;
96                 //printf("RSHIFT : %d\n", flag ? 1 : 0);
97         } else if(sc == 0x56) { // GRPH
98                 graph_pressed = flag;
99         } else if(sc == 0x55) { // CAPS
100                 // Toggle on press.
101                 if(flag) {
102                         if(caps_pressed) {
103                                 caps_pressed = false;
104                         } else {
105                                 caps_pressed = true;
106                         }
107                         if(keymode == KEYMODE_STANDARD) this->write_signals(&caps_led, caps_pressed ? 0xff : 0x00);
108                         //this->write_signals(&caps_led, caps_pressed ? 0xff : 0x00);
109                 }
110         } else if(sc == 0x5a) { // KANA
111                 // Toggle on press.
112                 if(flag) {
113                         if(kana_pressed) {
114                                 kana_pressed = false;
115                         } else {
116                                 kana_pressed = true;
117                         }
118                         if(keymode == KEYMODE_STANDARD) this->write_signals(&kana_led, kana_pressed ? 0xff : 0x00);
119                 }
120         } else if(sc == 0x5c) { // Break
121                 break_pressed = flag;
122         }
123 }
124
125 uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
126 {
127         const struct key_tbl_t *keyptr = NULL;
128         bool stdkey = false;
129         int i;
130         uint16 retval;
131         
132         if((sc == 0) || (sc >= 0x67)) return 0xffff;
133         // Set repeat flag(s)
134         if(shift_pressed && ctrl_pressed) {
135                 switch(sc) {
136                         case 0x02: // 1
137                         case 0x42: // 1
138                                 repeat_mode = true;
139                                 return 0xffff;
140                                 break;
141                         case 0x0b: // 0
142                         case 0x46: // 0
143                                 repeat_mode = false;
144                                 return 0xffff;
145                                 break;
146                 }
147         }
148         if(keymode == KEYMODE_STANDARD) {
149                 if(ctrl_pressed) {
150                         if(shift_pressed) {
151                                 keyptr = ctrl_shift_key;
152                         } else {
153                                 keyptr = ctrl_key;
154                         }
155                 } else if(graph_pressed) {
156                         if(shift_pressed) {
157                                 keyptr = graph_shift_key;
158                         } else {
159                                 keyptr = graph_key;
160                         }
161                 } else if(kana_pressed) {
162                         if(shift_pressed) {
163                                 keyptr = kana_shift_key;
164                         } else {
165                                 keyptr = kana_key;
166                         }
167                 } else { // Standard
168                         stdkey = true;
169                         if(shift_pressed) {
170                                 keyptr = standard_shift_key;
171                         } else {
172                                 keyptr = standard_key;
173                         }
174                 }
175         }
176 #if defined(_FM77AV_VARIANTS)
177         else    if(shift_pressed) {
178           // DO super-impose mode:
179           // F7 : PC
180           // F8 : IMPOSE (High brightness)
181           // F9 : IMPOSE (Low brightness)
182           // F10: TV
183         }
184         if(keymode == KEYMODE_SCAN) {
185                 retval = sc;
186                 return retval;
187         } else if(keymode == KEYMODE_16BETA) { // Will Implement
188                 if(ctrl_pressed) {
189                         if(shift_pressed) {
190                                 keyptr = ctrl_shift_key_16beta;
191                         } else {
192                                 keyptr = ctrl_key_16beta;
193                         }
194                 } else if(graph_pressed) {
195                         if(shift_pressed) {
196                                 keyptr = graph_shift_key_16beta;
197                         } else {
198                                 keyptr = graph_key_16beta;
199                         }
200                 } else if(kana_pressed) {
201                         if(shift_pressed) {
202                                 keyptr = kana_shift_key_16beta;
203                         } else {
204                                 keyptr = kana_key_16beta;
205                         }
206                 } else { // Standard
207                         stdkey = true;
208                         if(shift_pressed) {
209                                 keyptr = standard_shift_key_16beta;
210                         } else {
211                                 keyptr = standard_key_16beta;
212                         }
213                 }
214         }
215 #endif //_FM77AV_VARIANTS       
216         i = 0;
217         retval = 0xffff;
218         if (keyptr == NULL) return 0xffff;
219         do {
220                 if(keyptr[i].phy == sc) {
221                         retval = keyptr[i].code;
222                         break;
223                 }
224                 i++;
225         } while(keyptr[i].phy != 0xffff);
226         if(keyptr[i].phy == 0xffff) return 0x00;
227         if(stdkey) {
228                 if((retval >= 'A') && (retval <= 'Z')) {
229                         if(caps_pressed) {
230                                 retval += 0x20;
231                         }
232                 } else if((retval >= 'a') && (retval <= 'z')) {
233                         if(caps_pressed) {
234                                 retval -= 0x20;
235                         }
236                 }
237         }
238         return retval;
239 }
240
241 void KEYBOARD::key_up(uint32 vk)
242 {
243         uint16 bak_scancode = vk2scancode(vk);
244         bool stat_break = break_pressed;
245         older_vk = 0;
246         if(bak_scancode == 0) return;
247         if((event_keyrepeat >= 0) && (repeat_keycode == bak_scancode)) { // Not Break
248                 cancel_event(this, event_keyrepeat);
249                 event_keyrepeat = -1;
250                 repeat_keycode = 0;
251         }
252         //printf("Key: up: %04x\n", bak_scancode);
253         if(this->isModifier(bak_scancode)) {
254                 set_modifiers(bak_scancode, false);
255                 if(break_pressed != stat_break) { // Break key UP.
256                         this->write_signals(&break_line, 0x00);
257                 }
258         }
259         scancode = 0;
260         if((keymode == KEYMODE_SCAN) && (bak_scancode != 0)) { // Notify even key-up, when using SCAN mode.
261                 uint32 code = (bak_scancode & 0x7f) | 0x80;
262                 key_fifo->write(code);
263         }
264 }
265
266 void KEYBOARD::key_down(uint32 vk)
267 {
268         if(older_vk == vk) return;
269         older_vk = vk;
270         
271         scancode = vk2scancode(vk);
272 #if defined(_FM77AV_VARIANTS)
273         // Below are FM-77AV's hidden message , see :
274         // https://twitter.com/maruan/status/499558392092831745
275         //if(caps_pressed && kana_pressed) {
276         //      if(ctrl_pressed && lshift_pressed && rshift_pressed && graph_pressed) {
277         if(caps_pressed && kana_pressed && graph_pressed && shift_pressed && ctrl_pressed && !did_hidden_message_av_1) { // IT's deprecated key pressing
278                 if(scancode == 0x15) { // "T"
279                         if(event_hidden1_av < 0) {
280                                 hidden1_ptr = 0;
281                                 did_hidden_message_av_1 = true;
282                                 register_event(this,
283                                                 ID_KEYBOARD_HIDDENMESSAGE_AV,
284                                                 130.0 * 1000, true, &event_hidden1_av);
285                         }
286                         return;
287                 }
288         }
289 #endif 
290         key_down_main();
291 }
292
293 void KEYBOARD::key_down_main(void)
294 {
295         bool stat_break = break_pressed;
296         uint32 code;
297         if(scancode == 0) return;
298         if(this->isModifier(scancode)) {  // modifiers
299                 set_modifiers(scancode, true);
300                 if(break_pressed != stat_break) { // Break key Down.
301                         this->write_signals(&break_line, 0xff);
302                 }
303                 //printf("DOWN SCAN=%04x break=%d\n", scancode, break_pressed);
304                 if(keymode != KEYMODE_SCAN) return;
305         }
306         if(keymode == KEYMODE_SCAN) {
307                 code = scancode & 0x7f;
308         } else {
309                 code = scan2fmkeycode(scancode);
310         }
311         if(code != 0) {
312                 key_fifo->write(code);
313                 if((scancode < 0x5c) && (code != 0xffff) && (repeat_keycode == 0)) {
314                         double usec = (double)repeat_time_long * 1000.0;
315                         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
316                         event_keyrepeat = -1;
317                         repeat_keycode = (uint8)scancode;
318                         if(repeat_mode) register_event(this,
319                                                        ID_KEYBOARD_AUTOREPEAT_FIRST,
320                                                        usec, false, &event_keyrepeat);
321                 }
322         }
323    
324 }
325
326 #if defined(_FM77AV_VARIANTS)
327 void KEYBOARD::adjust_rtc(void)
328 {
329         p_emu->get_host_time(&cur_time);
330         rtc_yy = cur_time.year % 100;
331         rtc_mm = cur_time.month;
332         rtc_dd = cur_time.day;
333
334         rtc_dayofweek = cur_time.day_of_week;
335         if(rtc_count24h) {
336                 rtc_ispm = (cur_time.hour >= 12) ? true : false;
337                 rtc_hour = cur_time.hour % 12;
338         } else {
339                 rtc_ispm = false;
340                 rtc_hour = cur_time.hour;
341         }
342         rtc_minute = cur_time.minute;
343         rtc_sec = cur_time.second;
344         if(event_key_rtc >= 0) {
345                 cancel_event(this, event_key_rtc);
346         }
347         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
348 }
349 #endif
350
351 void KEYBOARD::do_repeatkey(uint16 sc)
352 {
353         uint16 code_7;
354         if((sc == 0) || (sc >= 0x67)) return; // scancode overrun.
355         if(!repeat_mode) {
356                 if(event_keyrepeat >= 0) {
357                         cancel_event(this, event_keyrepeat);
358                         event_keyrepeat = -1;
359                 }
360                 return;
361         }
362         code_7 = scan2fmkeycode(sc);
363         if(keymode == KEYMODE_SCAN) {
364                 code_7 = sc;
365         }
366         if(code_7 < 0x200) {
367                 key_fifo->write((uint32)code_7);
368         }
369 }
370
371 void KEYBOARD::event_callback(int event_id, int err)
372 {
373 #if defined(_FM77AV_VARIANTS)
374         if(event_id == ID_KEYBOARD_RXRDY_OK) {
375                 rxrdy_status = true;
376                 write_signals(&rxrdy, 0xff);
377         } else if(event_id == ID_KEYBOARD_RXRDY_BUSY) {
378                 rxrdy_status = false;
379                 write_signals(&rxrdy, 0x00);
380         } else if(event_id == ID_KEYBOARD_ACK) {
381                 key_ack_status = true;
382                 write_signals(&key_ack, 0xff);
383         } else if(event_id == ID_KEYBOARD_RTC_COUNTUP) {
384                 rtc_count();
385         } else if(event_id == ID_KEYBOARD_HIDDENMESSAGE_AV) {
386                 if(hidden_message_77av_1[hidden1_ptr] == 0x00) {
387                         cancel_event(this, event_hidden1_av);
388                         event_hidden1_av = -1;
389                         hidden1_ptr = 0;
390                 } else {
391                         key_fifo->write(hidden_message_77av_1[hidden1_ptr++]);
392                 }
393                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
394                 beep->write_signal(SIG_BEEP_ON, 1, 1);
395                 register_event(this,
396                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
397                        20.0 * 1000.0, false, NULL);
398         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_ON) {
399                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
400                 beep->write_signal(SIG_BEEP_ON, 1, 1);
401                 register_event(this,
402                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
403                        20.0 * 1000.0, false, NULL);
404
405         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_OFF) {
406                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
407                 beep->write_signal(SIG_BEEP_ON, 0, 1);
408         } else
409 #endif
410         if(event_id == ID_KEYBOARD_AUTOREPEAT_FIRST) {
411                 uint32 sc = (uint32)repeat_keycode;
412                 double usec = (double)repeat_time_short * 1000.0;
413
414                 if((sc >= 0x67) || (sc == 0) || (sc == 0x5c)) return; 
415                 do_repeatkey((uint16)sc);
416                 register_event(this,
417                                ID_KEYBOARD_AUTOREPEAT,
418                                usec, true, &event_keyrepeat);
419                 // Key repeat.
420         } else if(event_id == ID_KEYBOARD_AUTOREPEAT){
421                 if(repeat_keycode != 0) {
422                         do_repeatkey((uint16)repeat_keycode);
423                 } else {
424                         cancel_event(this, event_keyrepeat);
425                         event_keyrepeat = -1;
426                 }
427         } else if(event_id == ID_KEYBOARD_INT) {
428                 if(!(key_fifo->empty())) {
429                         keycode_7 = key_fifo->read();
430                         this->write_signals(&int_line, 0xffffffff);
431                 }
432         }
433 }
434
435 // Commands
436 void KEYBOARD::reset_unchange_mode(void)
437 {
438         repeat_time_short = 70; // mS
439         repeat_time_long = 700; // mS
440         repeat_mode = true;
441         older_vk = 0;
442
443         lshift_pressed = false;
444         rshift_pressed = false;
445         shift_pressed = false;
446         ctrl_pressed   = false;
447         graph_pressed = false;
448         kana_pressed = false;
449         caps_pressed = false;
450         //      ins_pressed = false;
451         datareg = 0x00;
452         repeat_keycode = 0x00;
453
454 #if defined(_FM77AV_VARIANTS)
455         cmd_fifo->clear();
456         data_fifo->clear();
457         if(event_key_rtc >= 0) {
458                 cancel_event(this, event_key_rtc);
459         }
460         register_event(this,ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
461
462         cmd_phase = 0;
463         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
464         event_keyrepeat = -1;
465    
466         if(event_hidden1_av >= 0) cancel_event(this, event_hidden1_av);
467         event_hidden1_av = -1;
468         hidden1_ptr = 0;
469 #endif
470         // Bus
471         this->write_signals(&break_line, 0x00);
472 #if defined(_FM77AV_VARIANTS)
473         rxrdy_status = false;
474         key_ack_status = true;
475         this->write_signals(&rxrdy, 0x00);                
476         this->write_signals(&key_ack, 0xff);              
477 #endif
478         this->write_signals(&kana_led, 0x00);             
479         this->write_signals(&caps_led, 0x00);             
480         this->write_signals(&ins_led, 0x00);
481 }
482
483
484 void KEYBOARD::reset(void)
485 {
486         keymode = KEYMODE_STANDARD;
487         scancode = 0x00;
488         //keycode_7 = 0x00; 
489         keycode_7 = 0xffffffff; 
490         reset_unchange_mode();
491 #if defined(_FM77AV_VARIANTS)  
492         adjust_rtc();
493         did_hidden_message_av_1 = false;
494 #endif
495         key_fifo->clear();
496         if(event_int >= 0) cancel_event(this, event_int);
497         register_event(this,
498                        ID_KEYBOARD_INT,
499                        20000.0, true, &event_int);
500         write_signals(&int_line, 0x00000000);
501         
502         write_signals(&kana_led, 0x00000000);
503         write_signals(&caps_led, 0x00000000);
504         write_signals(&ins_led,  0x00000000);
505 #if defined(_FM77AV_VARIANTS)  
506         write_signals(&rxrdy,    0xffffffff);
507         write_signals(&key_ack,  0x00000000);
508 #endif
509 }
510
511
512 #if defined(_FM77AV_VARIANTS)  
513 // 0xd431 : Read
514 uint8 KEYBOARD::read_data_reg(void)
515 {
516         if(!data_fifo->empty()) {
517                 datareg = data_fifo->read() & 0xff;
518         }
519         if(!data_fifo->empty()) {
520                 rxrdy_status = true;
521                 write_signals(&rxrdy, 0xff);
522         } else {
523                 rxrdy_status = false;
524                 write_signals(&rxrdy, 0x00);
525         }
526         return datareg;
527 }
528
529 // 0xd432
530 uint8 KEYBOARD::read_stat_reg(void)
531 {
532         uint8 data = 0xff;
533         if(rxrdy_status) {
534                 data &= 0x7f;
535         }
536         if(!key_ack_status) {
537                 data &= 0xfe;
538         }
539         // Digityze : bit0 = '0' when waiting,
540         return data;
541 }
542
543 void KEYBOARD::set_mode(void)
544 {
545         int count = cmd_fifo->count();
546         int cmd;
547         int mode;
548         if(count < 2) return;
549         cmd = cmd_fifo->read();
550         mode = cmd_fifo->read();
551         if(mode <= KEYMODE_SCAN) {
552                 keymode = mode;
553                 //printf("Keymode : %d\n", keymode);
554                 //reset_unchange_mode();
555                 if(scancode != 0) key_down_main(); 
556         }
557         cmd_fifo->clear();
558         data_fifo->clear(); // right?
559         rxrdy_status = false;
560         write_signals(&rxrdy, 0x00);
561 }
562
563 void KEYBOARD::get_mode(void)
564 {
565         int cmd;
566         int dummy;
567         cmd = cmd_fifo->read();
568         if(data_fifo->full()) {
569                 dummy = data_fifo->read();
570         }
571         data_fifo->write(keymode);
572         rxrdy_status = true;
573         write_signals(&rxrdy, 0xff);
574 }
575
576 void KEYBOARD::set_leds(void)
577 {
578         int count = cmd_fifo->count();
579         int cmd;
580         int ledvar;
581         if(count < 2) return;
582         cmd = cmd_fifo->read();
583         ledvar = cmd_fifo->read();
584         if(ledvar < 4) {
585                 if((ledvar & 0x02) != 0) {
586                         // Kana
587                         kana_pressed = ((ledvar & 0x01) == 0);
588                         write_signals(&kana_led, kana_pressed);
589                 } else {
590                         // Caps
591                         caps_pressed = ((ledvar & 0x01) == 0);
592                         write_signals(&caps_led, caps_pressed);
593                 }
594         }
595         cmd_fifo->clear();
596         data_fifo->clear(); // right?
597         rxrdy_status = false;
598         write_signals(&rxrdy, 0x00);
599 }
600
601 void KEYBOARD::get_leds(void)
602 {
603         uint8 ledvar = 0x00;
604         data_fifo->clear();
605         ledvar |= caps_pressed ? 0x01 : 0x00;
606         ledvar |= kana_pressed ? 0x02 : 0x00;
607         data_fifo->write(ledvar);
608         cmd_fifo->clear();
609         rxrdy_status = true;
610         write_signals(&rxrdy, 0xff);
611 }
612
613 void KEYBOARD::set_repeat_type(void)
614 {
615         int cmd;
616         int modeval;
617
618         cmd = cmd_fifo->read();
619         if(!cmd_fifo->empty()) {
620                 modeval = cmd_fifo->read();
621                 if((modeval < 2) && (modeval >= 0)) {
622                         repeat_mode = (modeval == 0);
623                         if(repeat_mode) {
624                                 //scancode = 0x00;
625                                 //keycode_7 = 0x00;
626                                 key_fifo->clear();
627                         }
628                 }
629         }
630         data_fifo->clear();
631         cmd_fifo->clear();
632         rxrdy_status = false;
633         write_signals(&rxrdy, 0x00);
634 }
635
636 void KEYBOARD::set_repeat_time(void)
637 {
638         int cmd;
639         uint32 time_high = 0;
640         uint32 time_low = 0;
641         cmd = cmd_fifo->read();
642         if(cmd_fifo->empty()) goto _end;
643         time_high = cmd_fifo->read();
644         if(cmd_fifo->empty()) goto _end;
645         time_low = cmd_fifo->read();
646 //      if(cmd_fifo->empty()) goto _end;
647 _end:
648         if((time_high == 0) || (time_low == 0)) {
649                 repeat_time_long = 700;
650                 repeat_time_short = 70;
651         } else {
652                 repeat_time_long = (int)time_high * 10;
653                 repeat_time_short = (int)time_low * 10;
654         }
655         data_fifo->clear();
656         cmd_fifo->clear();
657         rxrdy_status = false;
658         write_signals(&rxrdy, 0x00);
659 }
660
661 void KEYBOARD::set_rtc(void)
662 {
663         int cmd;
664         int tmp;
665         int localcmd;
666         if(cmd_fifo->count() < 9) return;
667         cmd = cmd_fifo->read();
668         localcmd = cmd_fifo->read();
669         // YY
670         tmp = cmd_fifo->read();
671         rtc_yy = ((tmp >> 4) * 10) | (tmp & 0x0f);
672         // MM
673         tmp = cmd_fifo->read();
674         rtc_mm = ((tmp >> 4) * 10) | (tmp & 0x0f);
675         // DD
676         tmp = cmd_fifo->read();
677         rtc_dd = (((tmp & 0x30) >> 4) * 10) | (tmp & 0x0f);
678         // DayOfWeek + Hour
679         tmp = cmd_fifo->read();
680         rtc_count24h = ((tmp & 0x08) != 0);
681         if(!rtc_count24h) {
682                 rtc_ispm = ((tmp & 0x04) != 0);
683         }
684         rtc_dayofweek = (tmp >> 4) % 0x07;
685         rtc_hour = ((tmp & 0x03) * 10);
686         // Low
687         tmp = cmd_fifo->read();
688         rtc_hour = rtc_hour | (tmp >> 4);
689         if(rtc_count24h) {
690           rtc_ispm = (rtc_hour >= 12);
691         }
692         rtc_minute = (tmp & 0x0f) * 10;
693         
694         tmp = cmd_fifo->read();
695         rtc_minute = rtc_minute | (tmp >> 4);
696         rtc_sec = (tmp & 0x0f) * 10;
697         
698         tmp = cmd_fifo->read();
699         rtc_sec = rtc_sec | (tmp >> 4);
700         
701         data_fifo->clear();
702         cmd_fifo->clear();
703         if(event_key_rtc >= 0) {
704                 cancel_event(this, event_key_rtc);
705         }
706         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
707         rxrdy_status = false;
708         write_signals(&rxrdy, 0x00);
709 }
710
711 void KEYBOARD::get_rtc(void)
712 {
713         int tmp;
714         data_fifo->clear();
715         // YY
716         tmp = ((rtc_yy / 10) << 4) | (rtc_yy % 10);
717         data_fifo->write(tmp);
718         // MM
719         tmp = ((rtc_mm / 10) << 4) | (rtc_mm % 10);
720         data_fifo->write(tmp);
721         // DD
722         tmp = ((rtc_dd / 10) << 4) | (rtc_dd % 10);
723         tmp = tmp | (0 << 6); // leap
724         data_fifo->write(tmp);
725         // DayOfWeek + Hour
726         tmp = rtc_dayofweek << 4;
727         tmp = tmp | (rtc_hour / 10);
728         if(rtc_count24h) {
729           tmp = tmp | 0x08;
730         } else {
731           if(rtc_ispm) {
732             tmp = tmp | 0x04;
733           }
734         }
735         data_fifo->write(tmp);
736         // Low
737         tmp = (rtc_hour % 10) << 4;
738         tmp = tmp | (rtc_minute / 10);
739         data_fifo->write(tmp);
740         
741         tmp = (rtc_minute % 10) << 4;
742         tmp = tmp | (rtc_sec / 10);
743         data_fifo->write(tmp);
744         
745         tmp = (rtc_sec % 10) << 4;
746         data_fifo->write(tmp);
747         
748         cmd_fifo->clear();
749         rxrdy_status = true;
750         write_signals(&rxrdy, 0xff);
751 }
752
753 const int rtc_month_days[12] = {
754         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
755 };
756
757 void KEYBOARD::rtc_count(void)
758 {
759         // count per 1sec
760         rtc_sec++;
761         if(rtc_sec >= 60) {
762                 rtc_sec = 0;
763                 rtc_minute++;
764                 if(rtc_minute >= 60) {
765                         rtc_minute = 0;
766                         rtc_hour++;
767                         if(rtc_count24h) {
768                                 rtc_ispm = (rtc_hour >= 12);
769                                 if(rtc_hour < 24) return;
770                         } else {
771                                 if(rtc_ispm) {
772                                         if(rtc_hour < 12) return;
773                                 } else {
774                                         if(rtc_hour < 12) return;
775                                         rtc_ispm = true;
776                                         rtc_hour = 0;
777                                         return;
778                                 }
779                         }
780                         // Day count up
781                         rtc_hour = 0;
782                         rtc_dd++;
783                         rtc_dayofweek++;
784                         if(rtc_dayofweek >= 7) rtc_dayofweek = 0;
785                         if(rtc_dd > rtc_month_days[rtc_mm]){
786                                 if((rtc_mm ==1) && (rtc_dd == 29)) {
787                                         if((rtc_yy % 4) == 0) return;
788                                 }
789                                 rtc_dd = 1;
790                                 rtc_mm++;
791                                 if(rtc_mm >= 12) {
792                                         rtc_yy++;
793                                         rtc_mm = 0;
794                                         if(rtc_yy >= 100) rtc_yy = 0;
795                                 }
796                         }
797                 }
798         }
799 }
800 #endif // FM77AV_VARIANTS
801
802 uint32 KEYBOARD::read_signal(int id)
803 {
804         if(id == SIG_FM7KEY_BREAK_KEY) {
805                 return break_pressed ? 0xfffffff : 0x00000000;
806         }
807         return 0;
808 }
809
810
811 void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
812 {
813         if(id == SIG_FM7KEY_SET_INSLED) {
814                 write_signals(&ins_led, data & mask);
815         }
816 #if defined(_FM77AV_VARIANTS)  
817          else if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
818                 /*
819                  * I refered XM7's sourcecode : VM/keyboard.c act of key-encoder.
820                  * Thanks to Ryu.Takegami and PI.
821                  */
822                 int count;
823                 if(!key_ack_status) return; // If (not(ACK)) noop.
824
825                 if(cmd_fifo->full()) {
826                         cmd_fifo->clear();
827                 }
828                 if(cmd_fifo->empty()) {
829                         cmd_phase = data & 0xff;
830                 }
831                 
832                 cmd_fifo->write(data & 0xff);
833                 count = cmd_fifo->count();
834                 
835                 rxrdy_status = false;
836                 key_ack_status = false;
837                 write_signals(&key_ack, 0x00);
838                 write_signals(&rxrdy, 0x00);
839             
840                 switch(cmd_phase) {
841                         case 0: // Set mode
842                                 if(count >= 2) {
843                                         set_mode();
844                                         if(keymode == KEYMODE_SCAN) key_down_main();
845                                         cmd_phase = -1;
846                                         cmd_fifo->clear();
847                                 }
848                                 break;
849                         case 1: // Get mode
850                                 get_mode();
851                                 cmd_fifo->clear();
852                                 cmd_phase = -1;
853                                 break;
854                         case 2: // Set LED Phase
855                                 if(count >= 2) {
856                                         set_leds();
857                                         if(keymode == KEYMODE_SCAN) key_down_main();
858                                         cmd_phase = -1;
859                                         cmd_fifo->clear();
860                                 }
861                                 break;
862                         case 3: // Get LED Phase
863                                 get_leds();
864                                 cmd_phase = -1;
865                                 cmd_fifo->clear();
866                                 break;
867                         case 4:
868                                 if(count >= 2) {
869                                         set_repeat_type();
870                                         cmd_phase = -1;
871                                         cmd_fifo->clear();
872                                 }
873                                 break;
874                         case 5:
875                                 if(count >= 3) {
876                                         set_repeat_time();
877                                         cmd_phase = -1;
878                                         cmd_fifo->clear();
879                                 }
880                                 break;
881                         case 0x80: // Communicate to/from RTC.
882                                 if(count == 1) {
883                                         rtc_set = false;
884                                 }
885                                 if(count == 2) {
886                                         if((data & 0xff) == 0) { // Get
887                                                 get_rtc();
888                                                 cmd_phase = -1;
889                                                 cmd_fifo->clear();
890                                         } else if((data & 0xff) == 1) { // Set
891                                                 rtc_set_flag = true;
892                                         } else { // Illegal
893                                                 cmd_fifo->clear();
894                                                 cmd_phase = -1;
895                                         }
896                                 }
897                                 if(rtc_set_flag) {
898                                         if(count >= 9) {
899                                                 set_rtc();
900                                                 cmd_fifo->clear();
901                                                 cmd_phase = -1;
902                                         }
903                                 }
904                                 break;
905                         case 0x81: // Digitize.
906                                 if(count >= 2) {
907                                         do_digitize(); // WILL Implement?
908                                         cmd_fifo->clear();
909                                         cmd_phase = -1;
910                                 }
911                                 break;
912                         case 0x82:
913                                 if(count >= 2) {
914                                         set_screen_mode(); // WILL Implement?
915                                         cmd_fifo->clear();
916                                         cmd_phase = -1;
917                                 }
918                                 break;
919                         case 0x83:
920                                 get_screen_mode(); // WILL Implement?
921                                 cmd_fifo->clear();
922                                 cmd_phase = -1;
923                                 break;
924                         case 0x84:
925                                 if(count >= 2) {
926                                         set_brightness(); // WILL Implement?
927                                         cmd_fifo->clear();
928                                         cmd_phase = -1;
929                                 }
930                                 break;
931                         default:
932                                 cmd_fifo->clear();
933                                 cmd_phase = -1;
934                                 break;
935                 }
936                 register_event(this, ID_KEYBOARD_ACK, 5, false, NULL); // Delay 5us until ACK is up.
937         } else if(id == SIG_FM7KEY_RXRDY) {
938                 rxrdy_status = ((data & mask) != 0);
939                 //write_signals(&rxrdy, (rxrdy_status) ? 0xffffffff : 0x00000000);
940         } else if(id == SIG_FM7KEY_ACK) {
941                 key_ack_status = ((data & mask) != 0);
942                 //write_signals(&key_ack, (key_ack_status) ? 0xffffffff : 0x00000000);
943         }
944
945 #endif
946 }
947
948 uint32 KEYBOARD::read_data8(uint32 addr)
949 {
950         uint32 retval = 0xff;
951         switch(addr) {
952                 case 0x00:
953                         retval = get_keycode_high();
954                         break;
955                 case 0x01:
956                         retval = get_keycode_low();
957                         break;
958 #if defined(_FM77AV_VARIANTS)                   
959                 case 0x31:
960                         retval = read_data_reg();
961                         break;
962                 case 0x32:
963                         retval = read_stat_reg();
964                         break;
965 #endif
966                 default:
967                         break;
968         }
969         return retval;
970 }
971
972 void KEYBOARD::write_data8(uint32 addr, uint32 data)
973 {
974         switch(addr) {
975 #if defined(_FM77AV_VARIANTS)                   
976                 case 0x31:
977                         this->write_signal(SIG_FM7KEY_PUSH_TO_ENCODER, data, 0x000000ff);
978                         break;
979 #endif
980         }
981 }
982
983 KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
984 {
985         p_vm = parent_vm;
986         p_emu = parent_emu;
987   
988         keycode_7 = 0xffffffff;
989    
990         ctrl_pressed = false; 
991         lshift_pressed = false; 
992         rshift_pressed = false; 
993         shift_pressed = false; 
994         graph_pressed = false;
995         caps_pressed = false;
996         kana_pressed = false;
997         break_pressed = false;
998         event_keyrepeat = -1;
999    
1000         keymode = KEYMODE_STANDARD;
1001 #if defined(_FM77AV_VARIANTS)
1002         cmd_fifo = new FIFO(16);
1003         data_fifo = new FIFO(16);
1004         rxrdy_status = true;
1005         key_ack_status = false;
1006         init_output_signals(&rxrdy);
1007         init_output_signals(&key_ack);
1008         
1009         rtc_count24h = false;
1010         rtc_dayofweek = 0;
1011         rtc_ispm = false;
1012         rtc_set = false;
1013         rtc_set_flag = false;
1014         rtc_yy = 0;
1015         rtc_mm = 0;
1016         rtc_dd = 0;
1017         rtc_hour = 0;
1018         rtc_minute = 0;
1019         rtc_sec = 0;
1020         event_key_rtc = -1;
1021         event_hidden1_av = -1;
1022         hidden1_ptr = 0;
1023 #endif
1024         key_fifo = new FIFO(256);
1025         event_int = -1;
1026
1027         init_output_signals(&break_line);
1028         init_output_signals(&int_line);
1029         
1030         init_output_signals(&kana_led);
1031         init_output_signals(&caps_led);
1032         init_output_signals(&ins_led);
1033 }
1034
1035 void KEYBOARD::release(void)
1036 {
1037 #if defined(_FM77AV_VARIANTS)
1038         cmd_fifo->release();
1039         data_fifo->release();
1040         delete cmd_fifo;
1041         delete data_fifo;
1042 #endif   
1043         key_fifo->release();
1044         delete key_fifo;
1045 }
1046
1047
1048
1049 KEYBOARD::~KEYBOARD()
1050 {
1051 }
1052
1053 #define STATE_VERSION 2
1054 void KEYBOARD::save_state(FILEIO *state_fio)
1055 {
1056         int ch;
1057         int addr;
1058         state_fio->FputUint32_BE(STATE_VERSION);
1059         state_fio->FputInt32_BE(this_device_id);
1060
1061         // Version 1
1062         {
1063                 int id;
1064                 state_fio->FputUint32_BE(keycode_7);
1065                 state_fio->FputInt32_BE(keymode);
1066            
1067                 state_fio->FputBool(ctrl_pressed);
1068                 state_fio->FputBool(lshift_pressed);
1069                 state_fio->FputBool(rshift_pressed);
1070                 state_fio->FputBool(shift_pressed);
1071                 state_fio->FputBool(graph_pressed);
1072                 state_fio->FputBool(caps_pressed);
1073                 state_fio->FputBool(kana_pressed);
1074                 state_fio->FputBool(break_pressed);
1075
1076                 state_fio->FputInt32_BE(event_keyrepeat);
1077            
1078                 state_fio->FputUint32(scancode);
1079                 state_fio->FputUint8(datareg);
1080                 state_fio->FputUint32(older_vk);
1081            
1082                 state_fio->FputBool(repeat_mode);
1083                 state_fio->FputInt32_BE(repeat_time_short);
1084                 state_fio->FputInt32_BE(repeat_time_long);
1085                 state_fio->FputUint8(repeat_keycode);
1086            
1087 #if defined(_FM77AV_VARIANTS)
1088                 state_fio->FputInt32_BE(event_key_rtc);
1089   
1090                 state_fio->FputUint8(rtc_yy);
1091                 state_fio->FputUint8(rtc_mm);
1092                 state_fio->FputUint8(rtc_dd);
1093                 state_fio->FputUint8(rtc_dayofweek);
1094                 state_fio->FputUint8(rtc_hour);
1095                 state_fio->FputUint8(rtc_minute);
1096                 state_fio->FputUint8(rtc_sec);
1097
1098                 state_fio->FputBool(rtc_count24h);
1099                 state_fio->FputBool(rtc_ispm);
1100
1101                 state_fio->FputBool(rtc_set);
1102                 state_fio->FputBool(rtc_set_flag);
1103                 state_fio->FputBool(rxrdy_status);
1104                 state_fio->FputBool(key_ack_status);
1105                 state_fio->FputInt32_BE(cmd_phase);
1106
1107                 state_fio->FputInt32_BE(event_hidden1_av);
1108                 state_fio->FputUint16_BE(hidden1_ptr);
1109
1110                 cmd_fifo->save_state((void *)state_fio);
1111                 data_fifo->save_state((void *)state_fio);
1112                 cur_time.save_state((void *)state_fio);
1113 #endif
1114                 state_fio->FputInt32_BE(event_int);
1115                 key_fifo->save_state((void *)state_fio);
1116         }
1117         // Version 2
1118         {
1119 #if defined(_FM77AV_VARIANTS)
1120                 state_fio->FputBool(did_hidden_message_av_1);
1121 #endif
1122         }
1123 }
1124
1125 bool KEYBOARD::load_state(FILEIO *state_fio)
1126 {
1127         int ch;
1128         int addr;
1129         uint32 version;
1130         
1131         version = state_fio->FgetUint32_BE();
1132         if(this_device_id != state_fio->FgetInt32_BE()) return false;
1133
1134         if(version >= 1) {
1135                 keycode_7 = state_fio->FgetUint32_BE();
1136                 keymode = state_fio->FgetInt32_BE();
1137            
1138                 ctrl_pressed = state_fio->FgetBool();
1139                 lshift_pressed = state_fio->FgetBool();
1140                 rshift_pressed = state_fio->FgetBool();
1141                 shift_pressed = state_fio->FgetBool();
1142                 graph_pressed = state_fio->FgetBool();
1143                 caps_pressed = state_fio->FgetBool();
1144                 kana_pressed = state_fio->FgetBool();
1145                 break_pressed = state_fio->FgetBool();
1146
1147                 event_keyrepeat = state_fio->FgetInt32_BE();
1148            
1149                 scancode = state_fio->FgetUint32();
1150                 datareg = state_fio->FgetUint8();
1151                 older_vk = state_fio->FgetUint32();
1152            
1153                 repeat_mode = state_fio->FgetBool();
1154                 repeat_time_short = state_fio->FgetInt32_BE();
1155                 repeat_time_long = state_fio->FgetInt32_BE();
1156                 repeat_keycode = state_fio->FgetUint8();
1157            
1158 #if defined(_FM77AV_VARIANTS)
1159                 event_key_rtc = state_fio->FgetInt32_BE();
1160                 rtc_yy = state_fio->FgetUint8();
1161                 rtc_mm = state_fio->FgetUint8();
1162                 rtc_dd = state_fio->FgetUint8();
1163                 rtc_dayofweek = state_fio->FgetUint8();
1164                 rtc_hour = state_fio->FgetUint8();
1165                 rtc_minute = state_fio->FgetUint8();
1166                 rtc_sec = state_fio->FgetUint8();
1167
1168                 rtc_count24h = state_fio->FgetBool();
1169                 rtc_ispm = state_fio->FgetBool();
1170
1171                 rtc_set = state_fio->FgetBool();
1172                 rtc_set_flag = state_fio->FgetBool();
1173                 rxrdy_status = state_fio->FgetBool();
1174                 key_ack_status = state_fio->FgetBool();
1175                 cmd_phase = state_fio->FgetInt32_BE();
1176
1177                 event_hidden1_av = state_fio->FgetInt32_BE();
1178                 hidden1_ptr = state_fio->FgetUint16_BE();
1179
1180                 cmd_fifo->load_state((void *)state_fio);
1181                 data_fifo->load_state((void *)state_fio);
1182                 cur_time.load_state((void *)state_fio);
1183 #endif
1184                 event_int = state_fio->FgetInt32_BE();
1185                 key_fifo->save_state((void *)state_fio);
1186                 if(version == 1) return true;
1187         }
1188         // Version 2
1189         {
1190                 bool flag = true;
1191 #if defined(_FM77AV_VARIANTS)
1192                 did_hidden_message_av_1 = state_fio->FgetBool();
1193 #endif
1194                 if(version == 2) {
1195                         return flag;
1196                 }
1197         }
1198         return false;
1199 }
1200
1201