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"
14 SIG_FM7KEY_KEY_UP = 0x800,
16 SIG_FM7KEY_READ, // D400 = high , D401 = low
17 SIG_FM7KEY_LED_ONOFF, // D40D: Write = OFF / Read = ON
19 SIG_FM7KEY_PUSH_TO_ENCODER,
29 uint16 vk_matrix[0x68] = { // VK
30 // +0, +1, +2, +3, +4, +5, +6, +7
31 /* 0x00, ESC, 1 , 2, 3, 4, 5, 6 */
32 0x00, VK_KANJI, '1', '2', '3', '4', '5', '6', // +0x00
33 /* 7, 8, 9, 0, - , ^, \|, BS */
34 '7', '8', '9', '0', 0xbd, 0xde, 0xdc, VK_BACK, // +0x08
35 /* TAB, Q, W, E, R, T, Y, U */
36 VK_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', // +0x10
37 /* I, O, P, @, [, [RET], A, S */
38 'I', 'O', 'P', 0xc0, 0xdb, VK_RETURN, 'A', 'S', //+0x18
39 /* D, F, G, H, J, K, L, ; */
40 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xbb, // +0x20
41 /* :, ], Z, X, C, V, B, N */
42 0xba, 0xdd, 'Z', 'X', 'C', 'V', 'B', 'N', // +0x28
43 /* M, , , ., / , \, RSPACE=RWIN , * , / */
44 'M', 0xbc, 0xbe, 0xbf, 0xe2, VK_RWIN, VK_MULTIPLY, VK_DIVIDE, // +0x30
45 /* + , - , 7, 8, 9, = , 4, 5 */
46 VK_ADD, VK_SUBTRACT, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, 0x00, VK_NUMPAD4, VK_NUMPAD5, // +0x38
47 /* 6, NUMPADCOMMA=RMENU , 1, 2, 3, NUMPADENTER=RETURN,0, . */
48 VK_NUMPAD6, VK_RMENU, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_RETURN, VK_NUMPAD0, VK_DECIMAL, // +0x40
49 /* INS, HOME, PRIOR, DEL, END, ↑, ↓,← */
50 VK_INSERT, VK_HOME, VK_PRIOR, VK_DELETE, VK_END, VK_UP, VK_NEXT, VK_LEFT, // +0x48
51 /* PAgeDown, →, LCTRL, LSHIFT, RSHIFT, CAPS, Graph=Muhenkan, Lspace=LALT */
52 VK_DOWN, VK_RIGHT, VK_LCONTROL, VK_LSHIFT, VK_RSHIFT, VK_CAPITAL, 0x1d, 0xf3, // +0x50
53 /* Cspace=Space, *Unknown*, KANA, *Unknown* , ESC(Break), F1, F2, F3 */
54 VK_SPACE, 0x00, 0xf2, 0x00, VK_ESCAPE, VK_F1, VK_F2, VK_F3, // +0x58
55 /* F4, F5, F6, F7, F8, F9, F10 , *END* */
56 VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, 0xffff // +0x60
64 // Key tables value from XM7.
65 const key_tbl_t standard_key[] = {
170 const key_tbl_t standard_shift_key[] = {
263 const struct key_tbl_t ctrl_key[] = {
303 const struct key_tbl_t ctrl_shift_key[] = {
343 const struct key_tbl_t graph_key[] = {
431 /* Belows is none when shift */
444 const struct key_tbl_t graph_shift_key[] = {
536 const struct key_tbl_t kana_key[] = {
643 const struct key_tbl_t kana_shift_key[] = {
710 uint8 KEYBOARD::read_data_reg(void)
712 if(rxrdy->read_signal(0) != 0) {
713 if(!data_fifo->empty()) {
714 datareg = data_fifo->read() & 0xff;
717 if(data_fifo->empty()) {
718 rxrdy->write_signal(0x00, 0x00, 0x01);
720 rxrdy->write_signal(0x00, 0x01, 0x01);
726 uint8 KEYBOARD::read_stat_reg(void)
730 if(!data_fifo->empty()) {
731 rxrdy->write_signal(0x00, 0x01, 0x01);
734 if(key_ack->read_signal(0) == 0x00) {
737 // Digityze : bit0 = '0' when waiting,
741 // 0xd400(SUB) or 0xfd00(MAIN)
742 uint8 KEYBOARD::get_keycode_high(void)
745 if((keycode_7 & 0x0100) != 0) data |= 0x01;
749 // 0xd401(SUB) or 0xfd01(MAIN)
750 uint8 KEYBOARD::get_keycode_low(void)
752 uint8 data = keycode_7 & 0xff;
753 maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
754 subcpu->write_signal(SIG_CPU_FIRQ, 0, 1);
759 void KEYBOARD::turn_on_ins_led(void)
761 ins_led->write_signal(0x00, 0x01, 0x01);
765 void KEYBOARD::turn_off_ins_led(void)
767 ins_led->write_signal(0x00, 0x00, 0x01);
773 uint16 KEYBOARD::vk2scancode(uint32 vk)
779 if(vk_matrix[i] == vk) return i;
781 } while(vk_matrix[i] != 0xffff);
785 bool KEYBOARD::isModifier(uint16 scancode)
787 if(((scancode >= 0x52) && (scancode <= 0x56)) || // CTRL LSHIFT RSHIFT CAPS GRPH
788 (scancode == 0x5a) || (scancode == 0x5c)) { // KANA BREAK
794 void KEYBOARD::set_modifiers(uint16 scancode, bool flag)
796 if(scancode == 0x52) { // CTRL
798 } else if(scancode == 0x53) { // LSHIFT
799 lshift_pressed = flag;
801 shift_pressed = true;
803 shift_pressed = flag;
805 } else if(scancode == 0x54) { // RSHIFT
806 rshift_pressed = flag;
808 shift_pressed = true;
810 shift_pressed = flag;
812 } else if(scancode == 0x56) { // GRPH
813 graph_pressed = flag;
814 } else if(scancode == 0x55) { // CAPS
818 caps_pressed = false;
822 if(keymode == KEYMODE_STANDARD) caps_led->write_signal(0x00, caps_pressed ? 0x01 : 0x00, 0x01);
824 } else if(scancode == 0x5a) { // KANA
828 kana_pressed = false;
832 if(keymode == KEYMODE_STANDARD) kana_led->write_signal(0x00, kana_pressed ? 0x01 : 0x00, 0x01);
834 } else if(scancode == 0x5c) { // Break
835 break_pressed = flag;
839 uint16 KEYBOARD::scan2fmkeycode(uint16 scancode)
841 struct key_tbl_t *keyptr;
847 if((scancode == 0) || (scancode >= 0x67)) return 0xffff;
848 // Set repeat flag(s)
849 if(shift_pressed && ctrl_pressed) {
864 // DO super-impose mode:
866 // F8 : IMPOSE (High brightness)
867 // F9 : IMPOSE (Low brightness)
870 if(keymode == KEYMODE_SCAN) {
873 } else if(keymode == KEYMODE_STANDARD) {
876 keyptr = ctrl_shift_key;
880 } else if(graphkey_pressed) {
882 keyptr = graph_shift_key;
886 } else if(kanakey_pressed) {
888 keyptr = kana_shift_key;
895 keyptr = standard_shift_key;
897 keyptr = standard_key;
900 if(keyptr == NULL) return 0xffff;
901 } else if(keymode == KEYMODE_16BETA) { // Will Implement
908 if(keyptr[i].phy == scancode) {
909 retval = keyptr[i].code;
913 } while(keyptr[i].phy != 0xffff);
916 if((retval >= 'A') && (retval <= 'Z')) {
920 } else if((retval >= 'a') && (retval <= 'z')) {
929 void KEYBOARD::key_up(uint32 vk)
931 uint16 scancode = vk2scancode(vk);
932 bool stat_break = break_pressed;
934 if(scancode == 0) return;
935 if(event_ids[scancode] >= 0){
936 cancel_event(this, event_ids[scancode]);
937 event_ids[scancode] = -1;
939 if(keymode == KEYMODE_SCAN) {
942 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
943 subcpu->write_signal(SIG_CPU_FIRQ, 1, 1);
946 if(this->isModifiers(scancode)) {
947 set_modifiers(scancode, false);
948 if(break_pressed != stat_break) { // Break key UP.
949 break_line->write_signal(0x00, 0, 1);
950 maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
953 key_pressed_flag[scancode] = false;
956 void KEYBOARD::key_down(uint32 vk)
958 double usec = (double)repeat_time_long * 1000.0;
960 uint16 scancode = vk2scancode(vk);
961 bool stat_break = break_pressed;
963 if(scancode == 0) return;
964 key_pressed_flag[scancode] = true;
966 code_7 = scan2fmkeycode(scancode);
969 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
970 subcpu->write_signal(SIG_CPU_FIRQ, 1, 1);
972 if(this->isModifiers(scancode)) { // modifiers
973 if(break_pressed != stat_break) { // Break key Down.
974 break_line->write_signal(0x00, 1, 1);
975 maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
978 // If repeat && !(PF) && !(BREAK)
979 if((repeat_mode) && (scancode < 0x5c) && (scancode != 0)) {
981 ID_KEYBOARD_AUTOREPEAT_FIRST + scancode,
982 usec, false, &event_ids[scancode]);
984 event_ids[scancode] = -1;
986 key_pressed_flag[scancode] = true;
990 void KEYBOARD::do_repeatkey(uint16 scancode)
993 if((scancode == 0) || (scancode >= 0x67)) return; // scancode overrun.
995 if(event_ids[scancode] >= 0) {
996 cancel_event(this, event_ids[scancode]);
997 event_ids[scancode] = -1;
1001 key_pressed_flag[scancode] = true;
1002 code_7 = scan2fmkeycode(scancode);
1003 if(code_7 < 0x200) {
1005 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
1006 subcpu->write_signal(SIG_CPU_FIRQ, 1, 1);
1008 //if(this->isModifiers(scancode)) { // modifiers
1009 //if(break_pressed != stat_break) { // Break key Down.
1010 // break_line->write_signal(0x00, 1, 1);
1011 // maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
1016 void KEYBOARD::event_callback(int event_id, int err)
1018 if(event_id == ID_KEYBOARD_RXRDY_OK) {
1019 rxrdy->write_signal(0x00, 0x01, 0x01);
1020 } else if(event_id == ID_KEYBOARD_RXRDY_BUSY) {
1021 rxrdy->write_signal(0x00, 0x00, 0x01);
1022 } else if(event_id == ID_KEYBOARD_ACK) {
1023 key_ack->write_signal(0x00, 0x01, 0x01);
1024 } else if((event_id >= ID_KEYBOARD_AUTOREPEAT_FIRST) && (event_id <= (ID_KEYBOARD_AUTOREPEAT_FIRST + 0x1ff))) {
1025 uint32 scancode = event_id - ID_KEYBOARD_AUTOREPEAT_FIRST;
1026 double usec = (double)repeat_time_short * 1000.0;
1028 if((scancode >= 0x67) || (scancode == 0)) return;
1029 do_repeatkey((uint16)scancode);
1030 register_event(this,
1031 ID_KEYBOARD_AUTOREPEAT + scancode,
1032 usec, true, &event_ids[scancode]);
1034 } else if((event_id >= ID_KEYBOARD_AUTOREPEAT) && (event_id <= (ID_KEYBOARD_AUTOREPEAT + 0x1ff))){
1035 uint32 scancode = event_id - ID_KEYBOARD_AUTOREPEAT;
1036 do_repeatkey((uint16)scancode);
1041 void KEYBOARD::reset_keyboard(void)
1043 repeat_time_short = 70; // mS
1044 repeat_time_long = 700; // mS
1048 lshift_pressed = false;
1049 rshift_pressed = false;
1050 ctrl_pressed = false;
1051 graph_pressed = false;
1052 // ins_pressed = false;
1057 rxrdy->write_signal(0x00, 0x00, 0x01);
1058 key_ack->write_signal(0x00, 0x01, 0x01);
1059 break_line->write_signal(0x00, 0, 1);
1061 ins_led->write_signal(0x00, 0x00, 0x01);
1062 caps_led->write_signal(0x00, 0x00, 0x01);
1063 kana_led->write_signal(0x00, 0x00, 0x01);
1066 void KEYBOARD::set_mode(void)
1068 int count = cmd_fifo->count();
1070 if(count < 2) return;
1071 cmd = cmd_fifo->read();
1072 keymode = cmd_fifo->read();
1073 if(keymode <= KEYMODE_SCAN) reset_keyboard();
1075 data_fifo->clear(); // right?
1076 rxrdy->write_signal(0x00, 0x00, 0x01);
1079 void KEYBOARD::get_mode(void)
1083 cmd = cmd_fifo->read();
1084 if(data_fifo->full()) {
1085 dummy = data_fifo->read();
1087 data_fifo->write(keymode);
1088 rxrdy->write_signal(0x01, 0x01, 0x01);
1091 void KEYBOARD::set_leds(void)
1093 int count = cmd_fifo->count();
1096 if(count < 2) return;
1097 cmd = cmd_fifo->read();
1098 ledvar = cmd_fifo->read();
1100 if((ledvar & 0x02) != 0) {
1102 kana_pressed = ((ledvar & 0x01) == 0);
1103 kana_led->write_signal(0x00, ~ledvar, 0x01);
1106 caps_pressed = ((ledvar & 0x01) == 0);
1107 caps_led->write_signal(0x00, ~ledvar, 0x01);
1111 data_fifo->clear(); // right?
1112 rxrdy->write_signal(0x01, 0x00, 0x01);
1115 void KEYBOARD::get_leds(void)
1117 uint8 ledvar = 0x00;
1119 ledvar |= caps_pressed ? 0x01 : 0x00;
1120 ledvar |= kana_pressed ? 0x02 : 0x00;
1121 data_fifo->write(ledvar);
1123 rxrdy->write_signal(0x01, 0x01, 0x01);
1126 void KEYBOARD::set_repeat_type(void)
1131 cmd = cmd_fifo->read();
1132 if(cmd_fifo->empty()) return;
1133 modeval = cmd_fifo->read();
1134 if((modeval >= 2) || (modeval < 0)) return;
1135 repeat_mode = (modeval == 0);
1138 rxrdy->write_signal(0x01, 0x00, 0x01);
1141 void KEYBOARD::set_repeat_time(void)
1146 cmd = cmd_fifo->read();
1147 if(cmd_fifo->empty()) return;
1148 time_high = cmd_fifo->read();
1149 if(cmd_fifo->empty()) return;
1150 time_low = cmd_fifo->read();
1151 if(cmd_fifo->empty()) return;
1153 if((time_high == 0) || (time_low == 0)) {
1154 repeat_time_long = 700;
1155 repeat_time_short = 70;
1157 repeat_time_long = time_high * 10;
1158 repeat_time_short = time_low * 10;
1162 rxrdy->write_signal(0x01, 0x00, 0x01);
1165 void KEYBOARD::set_rtc(void)
1170 if(cmd_fifo->count() < 9) return;
1171 cmd = cmd_fifo->read();
1172 localcmd = cmd_fifo->read();
1174 tmp = cmd_fifo->read();
1175 rtc_yy = ((tmp >> 4) * 10) | (tmp & 0x0f);
1177 tmp = cmd_fifo->read();
1178 rtc_mm = ((tmp >> 4) * 10) | (tmp & 0x0f);
1180 tmp = cmd_fifo->read();
1181 rtc_dd = (((tmp & 0x30) >> 4) * 10) | (tmp & 0x0f);
1183 tmp = cmd_fifo->read();
1184 rtc_count24h = ((tmp & 0x08) != 0);
1186 rtc_ispm = ((tmp & 0x04) != 0);
1188 rtc_dayofweek = (tmp >> 4) % 0x07;
1189 rtc_hh = ((tmp & 0x03) * 10);
1191 tmp = cmd_fifo->read();
1192 rtc_hh = rtc_hh | (tmp >> 4);
1194 rtc_ispm = (rtc_hh >= 12);
1196 rtc_minute = (tmp & 0x0f) * 10;
1198 tmp = cmd_fifo->read();
1199 rtc_minute = rtc_minute | (tmp >> 4);
1200 rtc_sec = (tmp & 0x0f) * 10;
1202 tmp = cmd_fifo->read();
1203 rtc_sec = rtc_sec | (tmp >> 4);
1207 rxrdy->write_signal(0x01, 0x00, 0x01);
1210 void KEYBOARD::get_rtc(void)
1217 tmp = ((rtc_yy / 10) << 4) | (rtc_yy % 10);
1218 data_fifo->write(tmp);
1220 tmp = ((rtc_mm / 10) << 4) | (rtc_mm % 10);
1221 data_fifo->write(tmp);
1223 tmp = ((rtc_dd / 10) << 4) | (rtc_dd % 10);
1224 tmp = tmp | (0 << 6); // leap
1225 data_fifo->write(tmp);
1227 tmp = rtc_dayofweek << 4;
1228 tmp = tmp | (rtc_hh / 10);
1236 data_fifo->write(tmp);
1238 tmp = (rtc_hh % 10) << 4;
1239 tmp = tmp | (rtc_mm / 10);
1240 data_fifo->write(tmp);
1242 tmp = (rtc_minute % 10) << 4;
1243 tmp = tmp | (rtc_sec / 10);
1244 data_fifo->write(tmp);
1246 tmp = (rtc_sec % 10) << 4;
1247 data_fifo->write(tmp);
1250 rxrdy->write_signal(0x01, 0x01, 0x01);
1253 const int rtc_month_days[12] = {
1254 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1257 void KEYBOARD::rtc_count(void)
1264 if(rtc_minute >= 60) {
1268 rtc_ispm = (rtc_hour >= 12);
1269 if(rtc_hour < 24) return;
1272 if(rtc_hour < 12) return;
1274 if(rtc_hour < 12) return;
1284 if(rtc_dayofweek >= 7) rtc_dayofweek = 0;
1285 if(rtc_dd > rtc_month_days[rtc_mm]){
1286 if((rtc_mm ==1) && (rtc_dd == 29)) {
1287 if((rtc_yy % 4) == 0) return;
1294 if(rtc_yy >= 100) rtc_yy = 0;
1300 void KEYBOARD::rtc_adjust(void)
1304 void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
1307 if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
1309 * I refered XM7's sourcecode : VM/keyboard.c act of key-encoder.
1310 * Thanks to Ryu.Takegami and PI.
1313 if(key_ack->read_signal(0x00) == 0) return; // If (not(ACK)) noop.
1315 if(cmd_fifo->full()) {
1318 if(cmd_fifo->empty()) {
1319 cmd_phase = data & 0xff;
1322 cmd_fifo->write(data & 0xff);
1323 count = cmd_fifo->count();
1325 key_ack->write_signal(0x00, 0x00, 0x01);
1328 if(count >= 2) set_mode();
1333 case 2: // Set LED Phase
1334 if(count >= 2) set_leds();
1336 case 3: // Get LED Phase
1340 if(count >= 2) set_repeat_type();
1343 if(count >= 3) set_repeat_time();
1345 case 0x80: // Communicate to/from RTC.
1350 if((data & 0xff) == 0) { // Get
1352 } else if((data & 0xff) == 1) { // Set
1353 rtc_set_flag = true;
1364 case 0x81: // Digitize.
1365 if(count >= 2) do_digitize(); // WILL Implement?
1368 if(count >= 2) set_screen_mode();
1374 if(count >= 2) set_brightness();
1377 //cmd_fifo->clear();
1380 register_event(this, ID_KEYBOARD_ACK, 5, false, NULL); // Delay 5us until ACK is up.