OSDN Git Service

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