OSDN Git Service

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