OSDN Git Service

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