OSDN Git Service

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