2 * Common Source code Project -> VM -> FM-7/77AV -> Keyboard
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
6 * Feb 12, 2015 : Initial
9 #include "../../fifo.h"
10 #include "../device.h"
11 #include "fm7_keyboard.h"
14 const uint16 vk_matrix_106[0x68] = { // VK
15 // +0, +1, +2, +3, +4, +5, +6, +7
16 /* 0x00, ESC, 1 , 2, 3, 4, 5, 6 */
17 0x00, VK_PAUSE, '1', '2', '3', '4', '5', '6', // +0x00
18 /* 7, 8, 9, 0, - , ^, \|, BS */
19 '7', '8', '9', '0', 0xbd, 0xde, 0xdc, VK_BACK, // +0x08
20 /* TAB, Q, W, E, R, T, Y, U */
21 VK_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', // +0x10
22 /* I, O, P, @, [, [RET], A, S */
23 'I', 'O', 'P', 0xc0, 0xdb, VK_RETURN, 'A', 'S', //+0x18
24 /* D, F, G, H, J, K, L, ; */
25 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xbb, // +0x20
26 /* :, ], Z, X, C, V, B, N */
27 0xba, 0xdd, 'Z', 'X', 'C', 'V', 'B', 'N', // +0x28
28 /* M, , , ., / , \, RSPACE=RWIN , * , / */
29 'M', 0xbc, 0xbe, 0xbf, 0xe2, VK_RWIN, VK_MULTIPLY, VK_DIVIDE, // +0x30
30 /* + , - , 7, 8, 9, = , 4, 5 */
31 VK_ADD, VK_SUBTRACT, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, 0x00, VK_NUMPAD4, VK_NUMPAD5, // +0x38
32 /* 6, NUMPADCOMMA=RMENU , 1, 2, 3, NUMPADENTER=RETURN,0, . */
33 VK_NUMPAD6, VK_RMENU, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_RETURN, VK_NUMPAD0, VK_DECIMAL, // +0x40
34 /* INS, HOME, PRIOR, DEL, END, ↑, ↓,← */
35 VK_INSERT, VK_HOME, VK_PRIOR, VK_DELETE, VK_END, VK_UP, VK_NEXT, VK_LEFT, // +0x48
36 /* PAgeDown, →, LCTRL, LSHIFT, RSHIFT, CAPS, Graph=Muhenkan, Lspace=LALT */
37 VK_DOWN, VK_RIGHT, 0x11, 0x10, VK_RSHIFT, 0x14, 0x1d, 0xf3, // +0x50
38 /* Cspace=Space, *Unknown*, KANA, *Unknown* , ESC(Break), F1, F2, F3 */
39 VK_SPACE, 0x00, 0x15, 0x00, VK_ESCAPE, VK_F1, VK_F2, VK_F3, // +0x58
40 /* F4, F5, F6, F7, F8, F9, F10 , *END* */
41 VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, 0xffff // +0x60
49 // Key tables value from XM7.
50 const key_tbl_t standard_key[] = {
155 const key_tbl_t standard_shift_key[] = {
248 const struct key_tbl_t ctrl_key[] = {
288 const struct key_tbl_t ctrl_shift_key[] = {
328 const struct key_tbl_t graph_key[] = {
416 /* Belows is none when shift */
429 const struct key_tbl_t graph_shift_key[] = {
521 const struct key_tbl_t kana_key[] = {
628 const struct key_tbl_t kana_shift_key[] = {
694 // 0xd400(SUB) or 0xfd00(MAIN)
695 uint8 KEYBOARD::get_keycode_high(void)
698 if((keycode_7 & 0x0100) != 0) data |= 0x01;
702 // 0xd401(SUB) or 0xfd01(MAIN)
703 uint8 KEYBOARD::get_keycode_low(void)
705 uint8 data = keycode_7 & 0xff;
706 mainio->write_signal(FM7_MAINIO_KEYBOARDIRQ, 0, 1);
707 display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 0, 1);
712 void KEYBOARD::turn_on_ins_led(void)
714 this->write_signals(&ins_led, 0xff);
718 void KEYBOARD::turn_off_ins_led(void)
720 this->write_signals(&ins_led, 0x00);
724 uint16 KEYBOARD::vk2scancode(uint32 vk)
729 if(vk_matrix_106[i] == vk) return i;
731 } while(vk_matrix_106[i] != 0xffff);
735 bool KEYBOARD::isModifier(uint16 scancode)
737 if(((scancode >= 0x52) && (scancode <= 0x56)) || // CTRL LSHIFT RSHIFT CAPS GRPH
738 (scancode == 0x5a) || (scancode == 0x5c)) { // KANA BREAK
744 void KEYBOARD::set_modifiers(uint16 scancode, bool flag)
746 if(scancode == 0x52) { // CTRL
748 } else if(scancode == 0x53) { // LSHIFT
749 lshift_pressed = flag;
751 shift_pressed = true;
753 shift_pressed = flag;
755 } else if(scancode == 0x54) { // RSHIFT
756 rshift_pressed = flag;
758 shift_pressed = true;
760 shift_pressed = flag;
762 } else if(scancode == 0x56) { // GRPH
763 graph_pressed = flag;
764 } else if(scancode == 0x55) { // CAPS
768 caps_pressed = false;
772 if(keymode == KEYMODE_STANDARD) this->write_signals(&caps_led, caps_pressed ? 0xff : 0x00);
774 } else if(scancode == 0x5a) { // KANA
778 kana_pressed = false;
782 if(keymode == KEYMODE_STANDARD) this->write_signals(&kana_led, kana_pressed ? 0xff : 0x00);
784 } else if(scancode == 0x5c) { // Break
785 break_pressed = flag;
789 uint16 KEYBOARD::scan2fmkeycode(uint16 scancode)
791 const struct key_tbl_t *keyptr;
797 if((scancode == 0) || (scancode >= 0x67)) return 0xffff;
798 // Set repeat flag(s)
799 if(shift_pressed && ctrl_pressed) {
813 if(keymode == KEYMODE_STANDARD) {
816 keyptr = ctrl_shift_key;
820 } else if(graph_pressed) {
822 keyptr = graph_shift_key;
826 } else if(kana_pressed) {
828 keyptr = kana_shift_key;
835 keyptr = standard_shift_key;
837 keyptr = standard_key;
840 if(keyptr == NULL) return 0xffff;
842 #if defined(_FM77AV_VARIANTS)
843 else if(shift_pressed) {
844 // DO super-impose mode:
846 // F8 : IMPOSE (High brightness)
847 // F9 : IMPOSE (Low brightness)
850 if(keymode == KEYMODE_SCAN) {
853 } else if(keymode == KEYMODE_16BETA) { // Will Implement
856 #endif //_FM77AV_VARIANTS
860 if(keyptr[i].phy == scancode) {
861 retval = keyptr[i].code;
865 } while(keyptr[i].phy != 0xffff);
868 if((retval >= 'A') && (retval <= 'Z')) {
872 } else if((retval >= 'a') && (retval <= 'z')) {
881 void KEYBOARD::key_up(uint32 vk)
883 uint16 scancode = vk2scancode(vk);
884 bool stat_break = break_pressed;
887 if(scancode == 0) return;
888 if(event_ids[scancode] >= 0){
889 cancel_event(this, event_ids[scancode]);
890 event_ids[scancode] = -1;
892 key_pressed_flag[scancode] = false;
893 if(this->isModifier(scancode)) {
894 set_modifiers(scancode, false);
895 if(break_pressed != stat_break) { // Break key UP.
896 //mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 0x00, 0xff);
897 this->write_signals(&break_line, 0x00);
901 if(keymode == KEYMODE_SCAN) {
902 code_7 = scan2fmkeycode(scancode);
905 //mainio->write_signal(FM7_MAINIO_PUSH_KEYBOARD, code_7, 0x1ff);
906 //mainio->write_signal(FM7_MAINIO_KEYBOARDIRQ, 0, 1);
907 //display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 0, 1);
912 void KEYBOARD::key_down(uint32 vk)
914 double usec = (double)repeat_time_long * 1000.0;
916 uint16 scancode = vk2scancode(vk);
917 bool stat_break = break_pressed;
918 //printf("VK=%04x SCAN=%04x break=%d\n", vk, scancode, stat_break);
920 if(scancode == 0) return;
921 key_pressed_flag[scancode] = true;
923 if(this->isModifier(scancode)) { // modifiers
924 set_modifiers(scancode, true);
925 if(break_pressed != stat_break) { // Break key Down.
926 //mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 0xff, 0xff);
927 this->write_signals(&break_line, 0xff);
930 code_7 = scan2fmkeycode(scancode);
933 mainio->write_signal(FM7_MAINIO_PUSH_KEYBOARD, code_7, 0x1ff);
934 mainio->write_signal(FM7_MAINIO_KEYBOARDIRQ, 1, 1);
935 display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 1, 1);
937 // If repeat && !(PF) && !(BREAK)
938 if((repeat_mode) && (scancode < 0x5c) && (scancode != 0)) {
940 ID_KEYBOARD_AUTOREPEAT_FIRST + scancode,
941 usec, false, &event_ids[scancode]);
943 event_ids[scancode] = -1;
945 key_pressed_flag[scancode] = true;
949 void KEYBOARD::do_repeatkey(uint16 scancode)
952 if((scancode == 0) || (scancode >= 0x67)) return; // scancode overrun.
954 if(event_ids[scancode] >= 0) {
955 cancel_event(this, event_ids[scancode]);
956 event_ids[scancode] = -1;
960 key_pressed_flag[scancode] = true;
961 code_7 = scan2fmkeycode(scancode);
964 mainio->write_signal(FM7_MAINIO_PUSH_KEYBOARD, code_7, 0x1ff);
965 mainio->write_signal(FM7_MAINIO_KEYBOARDIRQ, 1, 1);
966 display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 1, 1);
968 //if(this->isModifiers(scancode)) { // modifiers
969 //if(break_pressed != stat_break) { // Break key Down.
970 // break_line->write_signal(0x00, 1, 1);
971 // maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
976 void KEYBOARD::event_callback(int event_id, int err)
978 if(event_id == ID_KEYBOARD_RXRDY_OK) {
979 write_signals(&rxrdy, 0xff);
980 } else if(event_id == ID_KEYBOARD_RXRDY_BUSY) {
981 write_signals(&rxrdy, 0x00);
982 } else if(event_id == ID_KEYBOARD_ACK) {
983 write_signals(&key_ack, 0xff);
984 } else if((event_id >= ID_KEYBOARD_AUTOREPEAT_FIRST) && (event_id <= (ID_KEYBOARD_AUTOREPEAT_FIRST + 0x1ff))) {
985 uint32 scancode = event_id - ID_KEYBOARD_AUTOREPEAT_FIRST;
986 double usec = (double)repeat_time_short * 1000.0;
988 if((scancode >= 0x67) || (scancode == 0)) return;
989 do_repeatkey((uint16)scancode);
991 ID_KEYBOARD_AUTOREPEAT + scancode,
992 usec, true, &event_ids[scancode]);
994 } else if((event_id >= ID_KEYBOARD_AUTOREPEAT) && (event_id <= (ID_KEYBOARD_AUTOREPEAT + 0x1ff))){
995 uint32 scancode = event_id - ID_KEYBOARD_AUTOREPEAT;
996 do_repeatkey((uint16)scancode);
1001 void KEYBOARD::reset(void)
1003 repeat_time_short = 70; // mS
1004 repeat_time_long = 700; // mS
1008 lshift_pressed = false;
1009 rshift_pressed = false;
1010 ctrl_pressed = false;
1011 graph_pressed = false;
1012 // ins_pressed = false;
1017 this->write_signals(&break_line, 0x00);
1018 this->write_signals(&rxrdy, 0x00);
1019 this->write_signals(&key_ack, 0x00);
1020 this->write_signals(&kana_led, 0x00);
1021 this->write_signals(&caps_led, 0x00);
1022 this->write_signals(&ins_led, 0x00);
1025 #if defined(_FM77AV_VARIANTS)
1027 uint8 KEYBOARD::read_data_reg(void)
1029 if(rxrdy->read_signal(0) != 0) {
1030 if(!data_fifo->empty()) {
1031 datareg = data_fifo->read() & 0xff;
1034 if(data_fifo->empty()) {
1035 rxrdy->write_signal(0x00, 0x00, 0x01);
1037 rxrdy->write_signal(0x00, 0x01, 0x01);
1043 uint8 KEYBOARD::read_stat_reg(void)
1047 if(!data_fifo->empty()) {
1048 rxrdy->write_signal(0x00, 0x01, 0x01);
1051 if(key_ack->read_signal(0) == 0x00) {
1054 // Digityze : bit0 = '0' when waiting,
1058 void KEYBOARD::set_mode(void)
1060 int count = cmd_fifo->count();
1062 if(count < 2) return;
1063 cmd = cmd_fifo->read();
1064 keymode = cmd_fifo->read();
1065 if(keymode <= KEYMODE_SCAN) reset();
1067 data_fifo->clear(); // right?
1068 rxrdy->write_signal(0x00, 0x00, 0x01);
1071 void KEYBOARD::get_mode(void)
1075 cmd = cmd_fifo->read();
1076 if(data_fifo->full()) {
1077 dummy = data_fifo->read();
1079 data_fifo->write(keymode);
1080 rxrdy->write_signal(0x01, 0x01, 0x01);
1083 void KEYBOARD::set_leds(void)
1085 int count = cmd_fifo->count();
1088 if(count < 2) return;
1089 cmd = cmd_fifo->read();
1090 ledvar = cmd_fifo->read();
1092 if((ledvar & 0x02) != 0) {
1094 kana_pressed = ((ledvar & 0x01) == 0);
1095 kana_led.write_signal(0x00, ~ledvar, 0x01);
1098 caps_pressed = ((ledvar & 0x01) == 0);
1099 caps_led.write_signal(0x00, ~ledvar, 0x01);
1103 data_fifo->clear(); // right?
1104 rxrdy->write_signal(0x01, 0x00, 0x01);
1107 void KEYBOARD::get_leds(void)
1109 uint8 ledvar = 0x00;
1111 ledvar |= caps_pressed ? 0x01 : 0x00;
1112 ledvar |= kana_pressed ? 0x02 : 0x00;
1113 data_fifo->write(ledvar);
1115 rxrdy->write_signal(0x01, 0x01, 0x01);
1118 void KEYBOARD::set_repeat_type(void)
1123 cmd = cmd_fifo->read();
1124 if(cmd_fifo->empty()) return;
1125 modeval = cmd_fifo->read();
1126 if((modeval >= 2) || (modeval < 0)) return;
1127 repeat_mode = (modeval == 0);
1130 rxrdy->write_signal(0x01, 0x00, 0x01);
1133 void KEYBOARD::set_repeat_time(void)
1138 cmd = cmd_fifo->read();
1139 if(cmd_fifo->empty()) return;
1140 time_high = cmd_fifo->read();
1141 if(cmd_fifo->empty()) return;
1142 time_low = cmd_fifo->read();
1143 if(cmd_fifo->empty()) return;
1145 if((time_high == 0) || (time_low == 0)) {
1146 repeat_time_long = 700;
1147 repeat_time_short = 70;
1149 repeat_time_long = time_high * 10;
1150 repeat_time_short = time_low * 10;
1154 rxrdy->write_signal(0x01, 0x00, 0x01);
1157 void KEYBOARD::set_rtc(void)
1162 if(cmd_fifo->count() < 9) return;
1163 cmd = cmd_fifo->read();
1164 localcmd = cmd_fifo->read();
1166 tmp = cmd_fifo->read();
1167 rtc_yy = ((tmp >> 4) * 10) | (tmp & 0x0f);
1169 tmp = cmd_fifo->read();
1170 rtc_mm = ((tmp >> 4) * 10) | (tmp & 0x0f);
1172 tmp = cmd_fifo->read();
1173 rtc_dd = (((tmp & 0x30) >> 4) * 10) | (tmp & 0x0f);
1175 tmp = cmd_fifo->read();
1176 rtc_count24h = ((tmp & 0x08) != 0);
1178 rtc_ispm = ((tmp & 0x04) != 0);
1180 rtc_dayofweek = (tmp >> 4) % 0x07;
1181 rtc_hh = ((tmp & 0x03) * 10);
1183 tmp = cmd_fifo->read();
1184 rtc_hh = rtc_hh | (tmp >> 4);
1186 rtc_ispm = (rtc_hh >= 12);
1188 rtc_minute = (tmp & 0x0f) * 10;
1190 tmp = cmd_fifo->read();
1191 rtc_minute = rtc_minute | (tmp >> 4);
1192 rtc_sec = (tmp & 0x0f) * 10;
1194 tmp = cmd_fifo->read();
1195 rtc_sec = rtc_sec | (tmp >> 4);
1199 rxrdy->write_signal(0x01, 0x00, 0x01);
1202 void KEYBOARD::get_rtc(void)
1209 tmp = ((rtc_yy / 10) << 4) | (rtc_yy % 10);
1210 data_fifo->write(tmp);
1212 tmp = ((rtc_mm / 10) << 4) | (rtc_mm % 10);
1213 data_fifo->write(tmp);
1215 tmp = ((rtc_dd / 10) << 4) | (rtc_dd % 10);
1216 tmp = tmp | (0 << 6); // leap
1217 data_fifo->write(tmp);
1219 tmp = rtc_dayofweek << 4;
1220 tmp = tmp | (rtc_hh / 10);
1228 data_fifo->write(tmp);
1230 tmp = (rtc_hh % 10) << 4;
1231 tmp = tmp | (rtc_mm / 10);
1232 data_fifo->write(tmp);
1234 tmp = (rtc_minute % 10) << 4;
1235 tmp = tmp | (rtc_sec / 10);
1236 data_fifo->write(tmp);
1238 tmp = (rtc_sec % 10) << 4;
1239 data_fifo->write(tmp);
1242 rxrdy->write_signal(0x01, 0x01, 0x01);
1245 const int rtc_month_days[12] = {
1246 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1249 void KEYBOARD::rtc_count(void)
1256 if(rtc_minute >= 60) {
1260 rtc_ispm = (rtc_hour >= 12);
1261 if(rtc_hour < 24) return;
1264 if(rtc_hour < 12) return;
1266 if(rtc_hour < 12) return;
1276 if(rtc_dayofweek >= 7) rtc_dayofweek = 0;
1277 if(rtc_dd > rtc_month_days[rtc_mm]){
1278 if((rtc_mm ==1) && (rtc_dd == 29)) {
1279 if((rtc_yy % 4) == 0) return;
1286 if(rtc_yy >= 100) rtc_yy = 0;
1292 void KEYBOARD::rtc_adjust(void)
1295 #endif // FM77AV_VARIANTS
1297 void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
1299 if(id == SIG_FM7KEY_SET_INSLED) {
1300 write_signals(&ins_led, data & mask);
1302 #if defined(_FM77AV_VARIANTS)
1303 else if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
1305 * I refered XM7's sourcecode : VM/keyboard.c act of key-encoder.
1306 * Thanks to Ryu.Takegami and PI.
1309 if(key_ack->read_signal(0x00) == 0) return; // If (not(ACK)) noop.
1311 if(cmd_fifo->full()) {
1314 if(cmd_fifo->empty()) {
1315 cmd_phase = data & 0xff;
1318 cmd_fifo->write(data & 0xff);
1319 count = cmd_fifo->count();
1321 key_ack->write_signal(0x00, 0x00, 0x01);
1324 if(count >= 2) set_mode();
1329 case 2: // Set LED Phase
1330 if(count >= 2) set_leds();
1332 case 3: // Get LED Phase
1336 if(count >= 2) set_repeat_type();
1339 if(count >= 3) set_repeat_time();
1341 case 0x80: // Communicate to/from RTC.
1346 if((data & 0xff) == 0) { // Get
1348 } else if((data & 0xff) == 1) { // Set
1349 rtc_set_flag = true;
1360 case 0x81: // Digitize.
1361 if(count >= 2) do_digitize(); // WILL Implement?
1364 if(count >= 2) set_screen_mode();
1370 if(count >= 2) set_brightness();
1373 //cmd_fifo->clear();
1376 register_event(this, ID_KEYBOARD_ACK, 5, false, NULL); // Delay 5us until ACK is up.
1381 uint32 KEYBOARD::read_data8(uint32 addr)
1383 uint32 retval = 0xff;
1386 retval = (keycode_7 >> 8) & 0x80;
1389 retval = keycode_7 & 0xff;
1391 #if defined(_FM77AV_VARIANTS)
1393 retval = read_data_reg();
1396 retval = read_stat_reg();
1405 void KEYBOARD::write_data8(uint32 addr, uint32 data)
1408 #if defined(_FM77AV_VARIANTS)
1410 this->write_signal(SIG_FM7KEY_PUSH_TO_ENCODER, data, 0x000000ff);
1416 KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
1424 ctrl_pressed = false;
1425 lshift_pressed = false;
1426 rshift_pressed = false;
1427 shift_pressed = false;
1428 graph_pressed = false;
1429 caps_pressed = false;
1430 kana_pressed = false;
1431 break_pressed = false;
1433 for(i = 0; i < 0x70; i++) {
1435 key_pressed_flag[i] = false;
1438 cmd_fifo = new FIFO(16);
1439 data_fifo = new FIFO(16);
1440 keymode = KEYMODE_STANDARD;
1442 init_output_signals(&rxrdy);
1443 init_output_signals(&key_ack);
1445 init_output_signals(&break_line);
1447 init_output_signals(&kana_led);
1448 init_output_signals(&caps_led);
1449 init_output_signals(&ins_led);
1454 KEYBOARD::~KEYBOARD()