OSDN Git Service

[VM][FM7] Fix state save/load.
[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_t KEYBOARD::get_keycode_high(void)
37 {
38         uint8_t data = 0x00;
39         if((keycode_7 & 0x0100) != 0) data = 0x80;
40         return data;
41 }
42
43 // 0xd401(SUB) or 0xfd01(MAIN)
44 uint8_t KEYBOARD::get_keycode_low(void)
45 {
46         uint8_t 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_t KEYBOARD::vk2scancode(uint32_t vk)
65 {
66         uint16_t 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_t 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_t 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_t KEYBOARD::scan2fmkeycode(uint16_t sc)
126 {
127         const struct key_tbl_t *keyptr = NULL;
128         bool stdkey = false;
129         int i;
130         uint16_t 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_t vk)
242 {
243         uint16_t 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         if(keymode != KEYMODE_SCAN) {
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         } else {
260                 //scancode = 0;
261                 if((keymode == KEYMODE_SCAN) && (bak_scancode != 0)) { // Notify even key-up, when using SCAN mode.
262                         uint32_t code = (bak_scancode & 0x7f) | 0x80;
263                         key_fifo->write(code);
264                         scancode = bak_scancode;
265                 }
266         }
267 }
268
269 void KEYBOARD::key_down(uint32_t vk)
270 {
271         if(older_vk == vk) return;
272         older_vk = vk;
273         
274         scancode = vk2scancode(vk);
275 #if defined(_FM77AV_VARIANTS)
276         // Below are FM-77AV's hidden message , see :
277         // https://twitter.com/maruan/status/499558392092831745
278         //if(caps_pressed && kana_pressed) {
279         //      if(ctrl_pressed && lshift_pressed && rshift_pressed && graph_pressed) {
280         if(caps_pressed && kana_pressed && graph_pressed && shift_pressed && ctrl_pressed && !did_hidden_message_av_1) { // IT's deprecated key pressing
281                 if(scancode == 0x15) { // "T"
282                         if(event_hidden1_av < 0) {
283                                 hidden1_ptr = 0;
284                                 did_hidden_message_av_1 = true;
285                                 register_event(this,
286                                                 ID_KEYBOARD_HIDDENMESSAGE_AV,
287                                                 130.0 * 1000, true, &event_hidden1_av);
288                         }
289                         return;
290                 }
291         }
292 #endif 
293         key_down_main();
294 }
295
296 void KEYBOARD::key_down_main(void)
297 {
298         bool stat_break = break_pressed;
299         uint32_t code;
300         if(scancode == 0) return;
301         if(keymode == KEYMODE_SCAN) {
302                 code = scancode & 0x7f;
303                 if(code != 0) {
304                         key_fifo->write(code);
305                         // NOTE: With scan key code mode, auto repeat seems to be not effectable.
306                         // See : http://hanabi.2ch.net/test/read.cgi/i4004/1430836648/607
307                         // 20160409 K.Ohta
308                 }
309         } else {
310                 if(this->isModifier(scancode)) {  // modifiers
311                         set_modifiers(scancode, true);
312                         if(break_pressed != stat_break) { // Break key Down.
313                                 this->write_signals(&break_line, 0xff);
314                         }
315                         return;
316                 }
317                 code = scan2fmkeycode(scancode);
318                 if((code > 0x3ff) || (code == 0)) return;
319                 if(code != 0) {
320                         key_fifo->write(code);
321                         if(scancode < 0x5c) {
322                                 double usec = (double)repeat_time_long * 1000.0;
323                                 if((repeat_keycode == 0) && repeat_mode) {
324                                         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
325                                         event_keyrepeat = -1;
326                                         register_event(this,
327                                                                    ID_KEYBOARD_AUTOREPEAT_FIRST,
328                                                                    usec, false, &event_keyrepeat);
329                                 }
330                                 repeat_keycode = (uint8_t)scancode;
331                         }
332                 }
333         }
334 }
335
336 #if defined(_FM77AV_VARIANTS)
337 void KEYBOARD::adjust_rtc(void)
338 {
339         get_host_time(&cur_time);
340         rtc_yy = cur_time.year % 100;
341         rtc_mm = cur_time.month;
342         rtc_dd = cur_time.day;
343
344         rtc_dayofweek = cur_time.day_of_week;
345         if(rtc_count24h) {
346                 rtc_ispm = (cur_time.hour >= 12) ? true : false;
347                 rtc_hour = cur_time.hour % 12;
348         } else {
349                 rtc_ispm = false;
350                 rtc_hour = cur_time.hour;
351         }
352         rtc_minute = cur_time.minute;
353         rtc_sec = cur_time.second;
354         if(event_key_rtc >= 0) {
355                 cancel_event(this, event_key_rtc);
356         }
357         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
358 }
359 #endif
360
361 void KEYBOARD::do_repeatkey(uint16_t sc)
362 {
363         uint16_t code;
364         if((sc == 0) || (sc >= 0x5c)) return; // scancode overrun.
365         if(!repeat_mode) {
366                 if(event_keyrepeat >= 0) {
367                         cancel_event(this, event_keyrepeat);
368                         event_keyrepeat = -1;
369                 }
370                 return;
371         }
372         if(keymode == KEYMODE_SCAN) {
373                 code = sc & 0x7f;
374                 key_fifo->write((uint32_t)code); // Make
375                 //key_fifo->write((uint32_t)(code | 0x80)); // Break
376         } else {
377                 code = scan2fmkeycode(sc);
378                 if(code < 0x400) {
379                         key_fifo->write((uint32_t)code);
380                 }
381         }
382 }
383
384 void KEYBOARD::event_callback(int event_id, int err)
385 {
386 #if defined(_FM77AV_VARIANTS)
387         if(event_id == ID_KEYBOARD_RXRDY_OK) {
388                 rxrdy_status = true;
389                 write_signals(&rxrdy, 0xff);
390         } else if(event_id == ID_KEYBOARD_RXRDY_BUSY) {
391                 rxrdy_status = false;
392                 write_signals(&rxrdy, 0x00);
393         } else if(event_id == ID_KEYBOARD_ACK) {
394                 key_ack_status = true;
395                 write_signals(&key_ack, 0xff);
396         } else if(event_id == ID_KEYBOARD_RTC_COUNTUP) {
397                 rtc_count();
398         } else if(event_id == ID_KEYBOARD_HIDDENMESSAGE_AV) {
399                 if(hidden_message_77av_1[hidden1_ptr] == 0x00) {
400                         cancel_event(this, event_hidden1_av);
401                         event_hidden1_av = -1;
402                         hidden1_ptr = 0;
403                 } else {
404                         key_fifo->write(hidden_message_77av_1[hidden1_ptr++]);
405                 }
406                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
407                 beep->write_signal(SIG_BEEP_ON, 1, 1);
408                 register_event(this,
409                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
410                        20.0 * 1000.0, false, NULL);
411         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_ON) {
412                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
413                 beep->write_signal(SIG_BEEP_ON, 1, 1);
414                 register_event(this,
415                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
416                        20.0 * 1000.0, false, NULL);
417
418         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_OFF) {
419                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
420                 beep->write_signal(SIG_BEEP_ON, 0, 1);
421         } else
422 #endif
423         if(event_id == ID_KEYBOARD_AUTOREPEAT_FIRST) {
424                 uint32_t sc = (uint32_t)repeat_keycode;
425                 double usec = (double)repeat_time_short * 1000.0;
426
427                 do_repeatkey((uint16_t)sc);
428                 register_event(this,
429                                ID_KEYBOARD_AUTOREPEAT,
430                                usec, true, &event_keyrepeat);
431                 // Key repeat.
432         } else if(event_id == ID_KEYBOARD_AUTOREPEAT){
433                 if(repeat_keycode != 0) {
434                         do_repeatkey((uint16_t)repeat_keycode);
435                 } else {
436                         cancel_event(this, event_keyrepeat);
437                         event_keyrepeat = -1;
438                 }
439         } else if(event_id == ID_KEYBOARD_INT) {
440                 if(!(key_fifo->empty())) {
441                         keycode_7 = key_fifo->read();
442                         this->write_signals(&int_line, 0xffffffff);
443                 }
444         }
445 }
446
447 // Commands
448 void KEYBOARD::reset_unchange_mode(void)
449 {
450         repeat_time_short = 70; // mS
451         repeat_time_long = 700; // mS
452         repeat_mode = true;
453         older_vk = 0;
454
455         lshift_pressed = false;
456         rshift_pressed = false;
457         shift_pressed = false;
458         ctrl_pressed   = false;
459         graph_pressed = false;
460         kana_pressed = false;
461         caps_pressed = false;
462         //      ins_pressed = false;
463         datareg = 0x00;
464         repeat_keycode = 0x00;
465
466 #if defined(_FM77AV_VARIANTS)
467         cmd_fifo->clear();
468         data_fifo->clear();
469         if(event_key_rtc >= 0) {
470                 cancel_event(this, event_key_rtc);
471         }
472         register_event(this,ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
473
474         cmd_phase = 0;
475         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
476         event_keyrepeat = -1;
477    
478         if(event_hidden1_av >= 0) cancel_event(this, event_hidden1_av);
479         event_hidden1_av = -1;
480         hidden1_ptr = 0;
481 #endif
482         // Bus
483         this->write_signals(&break_line, 0x00);
484 #if defined(_FM77AV_VARIANTS)
485         rxrdy_status = false;
486         key_ack_status = true;
487         this->write_signals(&rxrdy, 0x00);                
488         this->write_signals(&key_ack, 0xff);              
489 #endif
490         this->write_signals(&kana_led, 0x00);             
491         this->write_signals(&caps_led, 0x00);             
492         this->write_signals(&ins_led, 0x00);
493 }
494
495
496 void KEYBOARD::reset(void)
497 {
498         keymode = KEYMODE_STANDARD;
499         scancode = 0x00;
500
501         keycode_7 = 0xffffffff; 
502         reset_unchange_mode();
503         this->write_signals(&int_line, 0x00000000);
504         key_fifo->clear();
505 #if defined(_FM77AV_VARIANTS)  
506         adjust_rtc();
507         did_hidden_message_av_1 = false;
508 #endif
509         if(event_int >= 0) cancel_event(this, event_int);
510         register_event(this,
511                        ID_KEYBOARD_INT,
512                        20000.0, true, &event_int);
513 //      register_event(this,
514 //                     ID_KEYBOARD_INT,
515 //                     5000.0, true, &event_int);
516 }
517
518
519 #if defined(_FM77AV_VARIANTS)  
520 // 0xd431 : Read
521 uint8_t KEYBOARD::read_data_reg(void)
522 {
523         if(!data_fifo->empty()) {
524                 datareg = data_fifo->read() & 0xff;
525         }
526         if(!data_fifo->empty()) {
527                 rxrdy_status = true;
528                 write_signals(&rxrdy, 0xff);
529         } else {
530                 rxrdy_status = false;
531                 write_signals(&rxrdy, 0x00);
532         }
533         return datareg;
534 }
535
536 // 0xd432
537 uint8_t KEYBOARD::read_stat_reg(void)
538 {
539         uint8_t data = 0xff;
540         if(rxrdy_status) {
541                 data &= 0x7f;
542         }
543         if(!key_ack_status) {
544                 data &= 0xfe;
545         }
546         // Digityze : bit0 = '0' when waiting,
547         return data;
548 }
549
550 void KEYBOARD::set_mode(void)
551 {
552         int count = cmd_fifo->count();
553         int cmd;
554         int mode;
555         if(count < 2) return;
556         cmd = cmd_fifo->read();
557         mode = cmd_fifo->read();
558         if(mode <= KEYMODE_SCAN) {
559                 keymode = mode;
560                 //printf("Keymode : %d\n", keymode);
561                 //reset_unchange_mode();
562                 if(scancode != 0) key_down_main(); 
563         }
564         cmd_fifo->clear();
565         data_fifo->clear(); // right?
566         rxrdy_status = false;
567         write_signals(&rxrdy, 0x00);
568 }
569
570 void KEYBOARD::get_mode(void)
571 {
572         int cmd;
573         int dummy;
574         cmd = cmd_fifo->read();
575         if(data_fifo->full()) {
576                 dummy = data_fifo->read();
577         }
578         data_fifo->write(keymode);
579         rxrdy_status = true;
580         write_signals(&rxrdy, 0xff);
581 }
582
583 void KEYBOARD::set_leds(void)
584 {
585         int count = cmd_fifo->count();
586         int cmd;
587         int ledvar;
588         if(count < 2) return;
589         cmd = cmd_fifo->read();
590         ledvar = cmd_fifo->read();
591         if(ledvar < 4) {
592                 if((ledvar & 0x02) != 0) {
593                         // Kana
594                         kana_pressed = ((ledvar & 0x01) == 0);
595                         write_signals(&kana_led, kana_pressed);
596                 } else {
597                         // Caps
598                         caps_pressed = ((ledvar & 0x01) == 0);
599                         write_signals(&caps_led, caps_pressed);
600                 }
601         }
602         cmd_fifo->clear();
603         data_fifo->clear(); // right?
604         rxrdy_status = false;
605         write_signals(&rxrdy, 0x00);
606 }
607
608 void KEYBOARD::get_leds(void)
609 {
610         uint8_t ledvar = 0x00;
611         data_fifo->clear();
612         ledvar |= caps_pressed ? 0x01 : 0x00;
613         ledvar |= kana_pressed ? 0x02 : 0x00;
614         data_fifo->write(ledvar);
615         cmd_fifo->clear();
616         rxrdy_status = true;
617         write_signals(&rxrdy, 0xff);
618 }
619
620 void KEYBOARD::set_repeat_type(void)
621 {
622         int cmd;
623         int modeval;
624
625         cmd = cmd_fifo->read();
626         if(!cmd_fifo->empty()) {
627                 modeval = cmd_fifo->read();
628                 if((modeval < 2) && (modeval >= 0)) {
629                         repeat_mode = (modeval == 0);
630                         if(repeat_mode) {
631                                 //scancode = 0x00;
632                                 //keycode_7 = 0x00;
633                                 key_fifo->clear();
634                         }
635                 }
636         }
637         data_fifo->clear();
638         cmd_fifo->clear();
639         rxrdy_status = false;
640         write_signals(&rxrdy, 0x00);
641 }
642
643 void KEYBOARD::set_repeat_time(void)
644 {
645         int cmd;
646         uint32_t time_high = 0;
647         uint32_t time_low = 0;
648         cmd = cmd_fifo->read();
649         if(cmd_fifo->empty()) goto _end;
650         time_high = cmd_fifo->read();
651         if(cmd_fifo->empty()) goto _end;
652         time_low = cmd_fifo->read();
653 _end:
654         if((time_high == 0) || (time_low == 0)) {
655                 repeat_time_long = 700;
656                 repeat_time_short = 70;
657         } else {
658                 repeat_time_long = (int)time_high * 10;
659                 repeat_time_short = (int)time_low * 10;
660         }
661         data_fifo->clear();
662         cmd_fifo->clear();
663         rxrdy_status = false;
664         write_signals(&rxrdy, 0x00);
665 }
666
667 void KEYBOARD::set_rtc(void)
668 {
669         int cmd;
670         int tmp;
671         int localcmd;
672         if(cmd_fifo->count() < 9) return;
673         cmd = cmd_fifo->read();
674         localcmd = cmd_fifo->read();
675         // YY
676         tmp = cmd_fifo->read();
677         rtc_yy = ((tmp >> 4) * 10) | (tmp & 0x0f);
678         // MM
679         tmp = cmd_fifo->read();
680         rtc_mm = ((tmp >> 4) * 10) | (tmp & 0x0f);
681         // DD
682         tmp = cmd_fifo->read();
683         rtc_dd = (((tmp & 0x30) >> 4) * 10) | (tmp & 0x0f);
684         // DayOfWeek + Hour
685         tmp = cmd_fifo->read();
686         rtc_count24h = ((tmp & 0x08) != 0);
687         if(!rtc_count24h) {
688                 rtc_ispm = ((tmp & 0x04) != 0);
689         }
690         rtc_dayofweek = (tmp >> 4) % 0x07;
691         rtc_hour = ((tmp & 0x03) * 10);
692         // Low
693         tmp = cmd_fifo->read();
694         rtc_hour = rtc_hour | (tmp >> 4);
695         if(rtc_count24h) {
696           rtc_ispm = (rtc_hour >= 12);
697         }
698         rtc_minute = (tmp & 0x0f) * 10;
699         
700         tmp = cmd_fifo->read();
701         rtc_minute = rtc_minute | (tmp >> 4);
702         rtc_sec = (tmp & 0x0f) * 10;
703         
704         tmp = cmd_fifo->read();
705         rtc_sec = rtc_sec | (tmp >> 4);
706         
707         data_fifo->clear();
708         cmd_fifo->clear();
709         if(event_key_rtc >= 0) {
710                 cancel_event(this, event_key_rtc);
711         }
712         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
713         rxrdy_status = false;
714         write_signals(&rxrdy, 0x00);
715 }
716
717 void KEYBOARD::get_rtc(void)
718 {
719         int tmp;
720         data_fifo->clear();
721         // YY
722         tmp = ((rtc_yy / 10) << 4) | (rtc_yy % 10);
723         data_fifo->write(tmp);
724         // MM
725         tmp = ((rtc_mm / 10) << 4) | (rtc_mm % 10);
726         data_fifo->write(tmp);
727         // DD
728         tmp = ((rtc_dd / 10) << 4) | (rtc_dd % 10);
729         tmp = tmp | (0 << 6); // leap
730         data_fifo->write(tmp);
731         // DayOfWeek + Hour
732         tmp = rtc_dayofweek << 4;
733         tmp = tmp | (rtc_hour / 10);
734         if(rtc_count24h) {
735           tmp = tmp | 0x08;
736         } else {
737           if(rtc_ispm) {
738             tmp = tmp | 0x04;
739           }
740         }
741         data_fifo->write(tmp);
742         // Low
743         tmp = (rtc_hour % 10) << 4;
744         tmp = tmp | (rtc_minute / 10);
745         data_fifo->write(tmp);
746         
747         tmp = (rtc_minute % 10) << 4;
748         tmp = tmp | (rtc_sec / 10);
749         data_fifo->write(tmp);
750         
751         tmp = (rtc_sec % 10) << 4;
752         data_fifo->write(tmp);
753         
754         cmd_fifo->clear();
755         rxrdy_status = true;
756         write_signals(&rxrdy, 0xff);
757 }
758
759 const int rtc_month_days[12] = {
760         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
761 };
762
763 void KEYBOARD::rtc_count(void)
764 {
765         // count per 1sec
766         rtc_sec++;
767         if(rtc_sec >= 60) {
768                 rtc_sec = 0;
769                 rtc_minute++;
770                 if(rtc_minute >= 60) {
771                         rtc_minute = 0;
772                         rtc_hour++;
773                         if(rtc_count24h) {
774                                 rtc_ispm = (rtc_hour >= 12);
775                                 if(rtc_hour < 24) return;
776                         } else {
777                                 if(rtc_ispm) {
778                                         if(rtc_hour < 12) return;
779                                 } else {
780                                         if(rtc_hour < 12) return;
781                                         rtc_ispm = true;
782                                         rtc_hour = 0;
783                                         return;
784                                 }
785                         }
786                         // Day count up
787                         rtc_hour = 0;
788                         rtc_dd++;
789                         rtc_dayofweek++;
790                         if(rtc_dayofweek >= 7) rtc_dayofweek = 0;
791                         if(rtc_dd > rtc_month_days[rtc_mm]){
792                                 if((rtc_mm ==1) && (rtc_dd == 29)) {
793                                         if((rtc_yy % 4) == 0) return;
794                                 }
795                                 rtc_dd = 1;
796                                 rtc_mm++;
797                                 if(rtc_mm >= 12) {
798                                         rtc_yy++;
799                                         rtc_mm = 0;
800                                         if(rtc_yy >= 100) rtc_yy = 0;
801                                 }
802                         }
803                 }
804         }
805 }
806 #endif // FM77AV_VARIANTS
807
808 uint32_t KEYBOARD::read_signal(int id)
809 {
810         if(id == SIG_FM7KEY_BREAK_KEY) {
811                 return break_pressed ? 0xfffffff : 0x00000000;
812         }
813         return 0;
814 }
815
816
817 void KEYBOARD::write_signal(int id, uint32_t data, uint32_t mask)
818 {
819         if(id == SIG_FM7KEY_SET_INSLED) {
820                 write_signals(&ins_led, data & mask);
821         }
822 #if defined(_FM77AV_VARIANTS)  
823          else if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
824                 /*
825                  * I refered XM7's sourcecode : VM/keyboard.c act of key-encoder.
826                  * Thanks to Ryu.Takegami and PI.
827                  */
828                 int count;
829                 if(!key_ack_status) return; // If (not(ACK)) noop.
830
831                 if(cmd_fifo->full()) {
832                         cmd_fifo->clear();
833                 }
834                 if(cmd_fifo->empty()) {
835                         cmd_phase = data & 0xff;
836                 }
837                 
838                 cmd_fifo->write(data & 0xff);
839                 count = cmd_fifo->count();
840                 
841                 rxrdy_status = false;
842                 key_ack_status = false;
843                 write_signals(&key_ack, 0x00);
844                 write_signals(&rxrdy, 0x00);
845             
846                 switch(cmd_phase) {
847                         case 0: // Set mode
848                                 if(count >= 2) {
849                                         set_mode();
850                                         if(keymode == KEYMODE_SCAN) key_down_main();
851                                         cmd_phase = -1;
852                                         cmd_fifo->clear();
853                                 }
854                                 break;
855                         case 1: // Get mode
856                                 get_mode();
857                                 cmd_fifo->clear();
858                                 cmd_phase = -1;
859                                 break;
860                         case 2: // Set LED Phase
861                                 if(count >= 2) {
862                                         set_leds();
863                                         if(keymode == KEYMODE_SCAN) key_down_main();
864                                         cmd_phase = -1;
865                                         cmd_fifo->clear();
866                                 }
867                                 break;
868                         case 3: // Get LED Phase
869                                 get_leds();
870                                 cmd_phase = -1;
871                                 cmd_fifo->clear();
872                                 break;
873                         case 4:
874                                 if(count >= 2) {
875                                         set_repeat_type();
876                                         cmd_phase = -1;
877                                         cmd_fifo->clear();
878                                 }
879                                 break;
880                         case 5:
881                                 if(count >= 3) {
882                                         set_repeat_time();
883                                         cmd_phase = -1;
884                                         cmd_fifo->clear();
885                                 }
886                                 break;
887                         case 0x80: // Communicate to/from RTC.
888                                 if(count == 1) {
889                                         rtc_set = false;
890                                 }
891                                 if(count == 2) {
892                                         if((data & 0xff) == 0) { // Get
893                                                 get_rtc();
894                                                 cmd_phase = -1;
895                                                 cmd_fifo->clear();
896                                         } else if((data & 0xff) == 1) { // Set
897                                                 rtc_set_flag = true;
898                                         } else { // Illegal
899                                                 cmd_fifo->clear();
900                                                 cmd_phase = -1;
901                                         }
902                                 }
903                                 if(rtc_set_flag) {
904                                         if(count >= 9) {
905                                                 set_rtc();
906                                                 cmd_fifo->clear();
907                                                 cmd_phase = -1;
908                                         }
909                                 }
910                                 break;
911                         case 0x81: // Digitize.
912                                 if(count >= 2) {
913                                         do_digitize(); // WILL Implement?
914                                         cmd_fifo->clear();
915                                         cmd_phase = -1;
916                                 }
917                                 break;
918                         case 0x82:
919                                 if(count >= 2) {
920                                         set_screen_mode(); // WILL Implement?
921                                         cmd_fifo->clear();
922                                         cmd_phase = -1;
923                                 }
924                                 break;
925                         case 0x83:
926                                 get_screen_mode(); // WILL Implement?
927                                 cmd_fifo->clear();
928                                 cmd_phase = -1;
929                                 break;
930                         case 0x84:
931                                 if(count >= 2) {
932                                         set_brightness(); // WILL Implement?
933                                         cmd_fifo->clear();
934                                         cmd_phase = -1;
935                                 }
936                                 break;
937                         default:
938                                 cmd_fifo->clear();
939                                 cmd_phase = -1;
940                                 break;
941                 }
942                 register_event(this, ID_KEYBOARD_ACK, 5, false, NULL); // Delay 5us until ACK is up.
943         } else if(id == SIG_FM7KEY_RXRDY) {
944                 rxrdy_status = ((data & mask) != 0);
945                 //write_signals(&rxrdy, (rxrdy_status) ? 0xffffffff : 0x00000000);
946         } else if(id == SIG_FM7KEY_ACK) {
947                 key_ack_status = ((data & mask) != 0);
948                 //write_signals(&key_ack, (key_ack_status) ? 0xffffffff : 0x00000000);
949         }
950
951 #endif
952 }
953
954 uint32_t KEYBOARD::read_data8(uint32_t addr)
955 {
956         uint32_t retval = 0xff;
957         switch(addr) {
958                 case 0x00:
959                         retval = get_keycode_high();
960                         break;
961                 case 0x01:
962                         retval = get_keycode_low();
963                         break;
964 #if defined(_FM77AV_VARIANTS)                   
965                 case 0x31:
966                         retval = read_data_reg();
967                         break;
968                 case 0x32:
969                         retval = read_stat_reg();
970                         break;
971 #endif
972                 default:
973                         break;
974         }
975         return retval;
976 }
977
978 void KEYBOARD::write_data8(uint32_t addr, uint32_t data)
979 {
980         switch(addr) {
981 #if defined(_FM77AV_VARIANTS)                   
982                 case 0x31:
983                         this->write_signal(SIG_FM7KEY_PUSH_TO_ENCODER, data, 0x000000ff);
984                         break;
985 #endif
986         }
987 }
988
989 KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
990 {
991         p_vm = parent_vm;
992         p_emu = parent_emu;
993         
994 #if defined(_FM77AV_VARIANTS)
995         beep = NULL;
996 #endif  
997         keycode_7 = 0xffffffff;
998    
999         ctrl_pressed = false; 
1000         lshift_pressed = false; 
1001         rshift_pressed = false; 
1002         shift_pressed = false; 
1003         graph_pressed = false;
1004         caps_pressed = false;
1005         kana_pressed = false;
1006         break_pressed = false;
1007         event_keyrepeat = -1;
1008    
1009         keymode = KEYMODE_STANDARD;
1010 #if defined(_FM77AV_VARIANTS)
1011         cmd_fifo = new FIFO(16);
1012         data_fifo = new FIFO(16);
1013         rxrdy_status = true;
1014         key_ack_status = false;
1015         initialize_output_signals(&rxrdy);
1016         initialize_output_signals(&key_ack);
1017         
1018         rtc_count24h = false;
1019         rtc_dayofweek = 0;
1020         rtc_ispm = false;
1021         rtc_set = false;
1022         rtc_set_flag = false;
1023         rtc_yy = 0;
1024         rtc_mm = 0;
1025         rtc_dd = 0;
1026         rtc_hour = 0;
1027         rtc_minute = 0;
1028         rtc_sec = 0;
1029         event_key_rtc = -1;
1030         event_hidden1_av = -1;
1031         hidden1_ptr = 0;
1032 #endif
1033         key_fifo = new FIFO(512);
1034         event_int = -1;
1035         
1036         initialize_output_signals(&break_line);
1037         initialize_output_signals(&int_line);
1038         
1039         initialize_output_signals(&kana_led);
1040         initialize_output_signals(&caps_led);
1041         initialize_output_signals(&ins_led);
1042 }
1043
1044 void KEYBOARD::release(void)
1045 {
1046 #if defined(_FM77AV_VARIANTS)
1047         cmd_fifo->release();
1048         data_fifo->release();
1049         delete cmd_fifo;
1050         delete data_fifo;
1051 #endif   
1052         key_fifo->release();
1053         delete key_fifo;
1054 }
1055
1056
1057
1058 KEYBOARD::~KEYBOARD()
1059 {
1060 }
1061
1062 #define STATE_VERSION 2
1063 void KEYBOARD::save_state(FILEIO *state_fio)
1064 {
1065         state_fio->FputUint32_BE(STATE_VERSION);
1066         state_fio->FputInt32_BE(this_device_id);
1067         p_emu->out_debug_log("Save State: KEYBOARD: id=%d ver=%d\n", this_device_id, STATE_VERSION);
1068
1069         // Version 1
1070         {
1071                 state_fio->FputUint32_BE(keycode_7);
1072                 state_fio->FputInt32_BE(keymode);
1073            
1074                 state_fio->FputBool(ctrl_pressed);
1075                 state_fio->FputBool(lshift_pressed);
1076                 state_fio->FputBool(rshift_pressed);
1077                 state_fio->FputBool(shift_pressed);
1078                 state_fio->FputBool(graph_pressed);
1079                 state_fio->FputBool(caps_pressed);
1080                 state_fio->FputBool(kana_pressed);
1081                 state_fio->FputBool(break_pressed);
1082
1083                 state_fio->FputInt32_BE(event_keyrepeat);
1084            
1085                 state_fio->FputUint32(scancode);
1086                 state_fio->FputUint8(datareg);
1087                 state_fio->FputUint32(older_vk);
1088            
1089                 state_fio->FputBool(repeat_mode);
1090                 state_fio->FputInt32_BE(repeat_time_short);
1091                 state_fio->FputInt32_BE(repeat_time_long);
1092                 state_fio->FputUint8(repeat_keycode);
1093            
1094 #if defined(_FM77AV_VARIANTS)
1095                 state_fio->FputInt32_BE(event_key_rtc);
1096   
1097                 state_fio->FputUint8(rtc_yy);
1098                 state_fio->FputUint8(rtc_mm);
1099                 state_fio->FputUint8(rtc_dd);
1100                 state_fio->FputUint8(rtc_dayofweek);
1101                 state_fio->FputUint8(rtc_hour);
1102                 state_fio->FputUint8(rtc_minute);
1103                 state_fio->FputUint8(rtc_sec);
1104
1105                 state_fio->FputBool(rtc_count24h);
1106                 state_fio->FputBool(rtc_ispm);
1107
1108                 state_fio->FputBool(rtc_set);
1109                 state_fio->FputBool(rtc_set_flag);
1110                 state_fio->FputBool(rxrdy_status);
1111                 state_fio->FputBool(key_ack_status);
1112                 state_fio->FputInt32_BE(cmd_phase);
1113
1114                 state_fio->FputInt32_BE(event_hidden1_av);
1115                 state_fio->FputUint16_BE(hidden1_ptr);
1116
1117                 cmd_fifo->save_state((void *)state_fio);
1118                 data_fifo->save_state((void *)state_fio);
1119                 cur_time.save_state((void *)state_fio);
1120 #endif
1121                 state_fio->FputInt32_BE(event_int);
1122                 key_fifo->save_state((void *)state_fio);
1123         }
1124         // Version 2
1125         {
1126 #if defined(_FM77AV_VARIANTS)
1127                 state_fio->FputBool(did_hidden_message_av_1);
1128 #endif
1129         }
1130 }
1131
1132 bool KEYBOARD::load_state(FILEIO *state_fio)
1133 {
1134         uint32_t version;
1135         
1136         version = state_fio->FgetUint32_BE();
1137         if(this_device_id != state_fio->FgetInt32_BE()) return false;
1138         p_emu->out_debug_log("Load State: KEYBOARD: id=%d ver=%d\n", this_device_id, version);
1139
1140         if(version >= 1) {
1141                 keycode_7 = state_fio->FgetUint32_BE();
1142                 keymode = state_fio->FgetInt32_BE();
1143            
1144                 ctrl_pressed = state_fio->FgetBool();
1145                 lshift_pressed = state_fio->FgetBool();
1146                 rshift_pressed = state_fio->FgetBool();
1147                 shift_pressed = state_fio->FgetBool();
1148                 graph_pressed = state_fio->FgetBool();
1149                 caps_pressed = state_fio->FgetBool();
1150                 kana_pressed = state_fio->FgetBool();
1151                 break_pressed = state_fio->FgetBool();
1152
1153                 event_keyrepeat = state_fio->FgetInt32_BE();
1154            
1155                 scancode = state_fio->FgetUint32();
1156                 datareg = state_fio->FgetUint8();
1157                 older_vk = state_fio->FgetUint32();
1158            
1159                 repeat_mode = state_fio->FgetBool();
1160                 repeat_time_short = state_fio->FgetInt32_BE();
1161                 repeat_time_long = state_fio->FgetInt32_BE();
1162                 repeat_keycode = state_fio->FgetUint8();
1163            
1164 #if defined(_FM77AV_VARIANTS)
1165                 event_key_rtc = state_fio->FgetInt32_BE();
1166                 rtc_yy = state_fio->FgetUint8();
1167                 rtc_mm = state_fio->FgetUint8();
1168                 rtc_dd = state_fio->FgetUint8();
1169                 rtc_dayofweek = state_fio->FgetUint8();
1170                 rtc_hour = state_fio->FgetUint8();
1171                 rtc_minute = state_fio->FgetUint8();
1172                 rtc_sec = state_fio->FgetUint8();
1173
1174                 rtc_count24h = state_fio->FgetBool();
1175                 rtc_ispm = state_fio->FgetBool();
1176
1177                 rtc_set = state_fio->FgetBool();
1178                 rtc_set_flag = state_fio->FgetBool();
1179                 rxrdy_status = state_fio->FgetBool();
1180                 key_ack_status = state_fio->FgetBool();
1181                 cmd_phase = state_fio->FgetInt32_BE();
1182
1183                 event_hidden1_av = state_fio->FgetInt32_BE();
1184                 hidden1_ptr = state_fio->FgetUint16_BE();
1185
1186                 cmd_fifo->load_state((void *)state_fio);
1187                 data_fifo->load_state((void *)state_fio);
1188                 cur_time.load_state((void *)state_fio);
1189 #endif
1190                 event_int = state_fio->FgetInt32_BE();
1191                 key_fifo->load_state((void *)state_fio);
1192                 if(version == 1) return true;
1193         }
1194         // Version 2
1195         {
1196 #if defined(_FM77AV_VARIANTS)
1197                 did_hidden_message_av_1 = state_fio->FgetBool();
1198 #endif
1199         }
1200         if(version == STATE_VERSION) {
1201                 return true;
1202         }
1203         return false;
1204 }
1205
1206