Annotation of nono/vm/x68kkbd.cpp, revision 1.1.1.5

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.5 ! root        7: // 送信タイミングについて
        !             8: //     キーボードは MFP の USART に繋がっている。
        !             9: //     MFP USART の RR 線 (Receiver Ready) は受信可能なら 'H'、受信中は 'L' に
        !            10: //     なっている。キーボードは RR が 'H' の時だけデータを送信する。また、
        !            11: //     システムポート#4 の KEY CTRL = 0 (キーデータ送信不可) はこの RR を
        !            12: //     'L' に落とす AND 回路になっている。キーボードからの送信は 2400bps、
        !            13: //     ストップビット1、パリティなしなので、1バイトの送信に 3.75 msec かかる。
        !            14: //     実装では、キーボードは MFP の RR が 'H' なら MFP にキーデータを送信。
        !            15: //     MFP 側で RR を 'L' にして 3.75 msec をイベントで待った後、キーを処理
        !            16: //     して RR を 'H' に戻すことにする。
        !            17: 
        !            18: // SHIFT キーについては keyboard.cpp のコメントを参照。
1.1.1.4   root       19: 
1.1       root       20: #include "x68kkbd.h"
                     21: #include "mfp.h"
1.1.1.5 ! root       22: #include "sysport.h"
1.1       root       23: 
                     24: // コンストラクタ
                     25: X68030Keyboard::X68030Keyboard()
                     26: {
1.1.1.4   root       27:        led.resize(7);
1.1.1.3   root       28: }
                     29: 
                     30: // デストラクタ
                     31: X68030Keyboard::~X68030Keyboard()
                     32: {
                     33: }
                     34: 
1.1.1.4   root       35: // 本体リセットスイッチによるリセット
                     36: void
                     37: X68030Keyboard::ResetHard()
1.1.1.3   root       38: {
1.1.1.5 ! root       39:        inherited::ResetHard();
        !            40: 
1.1.1.4   root       41:        rept_delay = 500;
                     42:        rept_time  = 110;
                     43: 
                     44:        for (int i = 0; i < led.size(); i++) {
                     45:                led[i] = false;
                     46:        }
                     47:        led_darkness = 0;
1.1       root       48: }
                     49: 
1.1.1.5 ! root       50: // 共通キーコードを X680x0 キーコードに変換して返す。
        !            51: // 対応する X680x0 のキーがなければ 0 を返す。
        !            52: uint
        !            53: X68030Keyboard::KeyToMDKey(uint keycode) const
1.1       root       54: {
1.1.1.5 ! root       55:        if (keycode >= countof(keycode2x68kkey_table)) {
        !            56:                return 0;
        !            57:        }
1.1       root       58: 
1.1.1.5 ! root       59:        return keycode2x68kkey_table[keycode];
        !            60: }
        !            61: 
        !            62: // シフト状態なら true を返す
        !            63: bool
        !            64: X68030Keyboard::IsShift() const
        !            65: {
        !            66:        return pressed[KC_SHIFT];
        !            67: }
1.1       root       68: 
1.1.1.5 ! root       69: // keycode を前処理して返す。
        !            70: uint
        !            71: X68030Keyboard::PreprocessKey(uint keystat)
        !            72: {
        !            73:        // X68k のキーボードは左右の [SHIFT] の区別がない。
        !            74:        // KC_SHIFT_L はホストの物理キー左 [SHIFT] に対応、
        !            75:        // KC_SHIFT_R はホストの物理キー右 [SHIFT] に対応、
        !            76:        // KC_SHIFT はソフトウェアキーボードからの左右のない [SHIFT] に対応。
        !            77:        // どのキーコードで問い合わせをされても KC_SHIFT_L と KC_SHIFT_R の OR が
        !            78:        // [SHIFT] キーの状態である。
        !            79: 
        !            80:        uint keycode = KC_CODE(keystat);
        !            81: 
        !            82:        if (keycode == KC_SHIFT_L || keycode == KC_SHIFT_R) {
        !            83:                // KC_SHIFT_L, R に対する pressed は内部の OR 処理用
        !            84:                pressed[keycode] = KC_IS_MAKE(keystat);
        !            85:                if (keycode == KC_SHIFT_L && pressed[KC_SHIFT_R]) {
        !            86:                        return KC_none;
        !            87:                }
        !            88:                if (keycode == KC_SHIFT_R && pressed[KC_SHIFT_L]) {
        !            89:                        return KC_none;
        !            90:                }
        !            91:                return KC_SHIFT | KC_FLAG(keystat);
        !            92:        } else {
        !            93:                return keystat;
1.1       root       94:        }
1.1.1.5 ! root       95: }
        !            96: 
        !            97: #if 0
        !            98: // ProcessKey で処理することがいまのところ無い
1.1       root       99: 
1.1.1.5 ! root      100: // キー処理 (MD固有部分)
        !           101: bool
        !           102: X68030Keyboard::ProcessKey(uint keystat)
        !           103: {
1.1.1.4   root      104:        // LED は MPU 側から点灯/消灯指示が来るのでここでは何もしなくてよい
1.1       root      105: 
1.1.1.5 ! root      106:        // XXX ここでキーリピート?
        !           107: 
        !           108:        return true;
1.1       root      109: }
1.1.1.5 ! root      110: #endif
        !           111: 
        !           112: // MFP、システムポートと、キーボードの関係。
        !           113: //
        !           114: // キーボードの Ready 信号は MFP の RR とシステムポートの KeyCtrl の
        !           115: // AND で作られているが、この AND 部分はキーボードが担当することにする。
        !           116: // そのほうが都合がいいため。
        !           117: //
        !           118: //                 <- 本体 || キーボード ->
        !           119: //   MFP                   ||
        !           120: // --------+     :         ||  +-----
        !           121: //         |     :  +--+   ||  |
        !           122: //       RR|o-------|   |  ||  |
        !           123: // --------+     :  |    |-----|T0 (Ready)
        !           124: //            +-----|   |  ||  |
        !           125: //  Sysport   |  :  +--+   ||  |
        !           126: // --------+  |  :         ||  |
        !           127: //  KeyCtrl|--+  :         ||  +-----
        !           128: //         |     :         ||
        !           129: //               :エミュレータでは点線から右をキーボードが担当
1.1       root      130: 
1.1.1.5 ! root      131: // キーデータを送信
1.1       root      132: void
1.1.1.5 ! root      133: X68030Keyboard::SendStart()
1.1       root      134: {
1.1.1.5 ! root      135:        if (gMFP->RxIsReady()) {
        !           136:                // 本体が Ready ならここで送信
        !           137:                Ready();
        !           138:        } else {
        !           139:                // そうでない場合、ここでは処理は不要。
        !           140:                // MFP 側が受信可能になると Ready() がコールされ、そっちで処理される
1.1       root      141:        }
                    142: }
                    143: 
1.1.1.5 ! root      144: // MFP からの Ready 通知
        !           145: // 実際にはキーボード側が MFP (を含む本体側) が Ready になるのを待っている
        !           146: // のだが、待っているを作るのは大変なので。
1.1.1.2   root      147: void
1.1.1.5 ! root      148: X68030Keyboard::Ready()
1.1.1.2   root      149: {
1.1.1.5 ! root      150:        if (gSysport->GetKeyCtrl()) {
        !           151:                // KEYCTRL が有効なら処理する
        !           152: 
        !           153:                // ここで取り出せるのは keystat。
        !           154:                uint keystat;
        !           155:                if (sendqueue.Dequeue(&keystat)) {
        !           156:                        // あれば送信
        !           157: 
        !           158:                        // 呼ばれたからには送信できるはず
        !           159:                        assert(gMFP->RxIsReady() == true);
        !           160: 
        !           161:                        uint keycode = KC_CODE(keystat);
        !           162:                        // ここで X68k キーコードに変換 (変換できないはずはない)
        !           163:                        uint x68kkey = KeyToMDKey(keycode);
        !           164:                        assert(x68kkey != 0);
        !           165: 
        !           166:                        // 送信
        !           167:                        if (KC_IS_BREAK(keystat)) {
        !           168:                                x68kkey |= 0x80;
        !           169:                        }
        !           170:                        gMFP->Rx(x68kkey);
        !           171:                } else {
        !           172:                        // なければ何もせず終了
        !           173:                }
        !           174:        } else {
        !           175:                // KEYCTRL が無効なら何もしないだけでなく、キューをクリア。
        !           176:                // KEYCTRL が無効から有効になった時に、無効だった期間のキーデータを
        !           177:                // 吐き出すのはおかしいので。
        !           178:                sendqueue.Clear();
        !           179:        }
1.1.1.2   root      180: }
                    181: 
1.1.1.5 ! root      182: // マウス入力
1.1.1.4   root      183: void
1.1.1.5 ! root      184: X68030Keyboard::MouseInput(int x, int y, bool rb, bool lb, bool mb)
1.1.1.4   root      185: {
                    186: }
                    187: 
                    188: // ホストからの制御
                    189: void
                    190: X68030Keyboard::Command(uint32 data)
                    191: {
                    192:        if (data < 0x40) {
                    193:                // $00-$3f TV 制御
                    194:                // (実装不要)
                    195:                putlog(2, "Command TV 制御 $%02x", (data & 0x1f));
                    196: 
                    197:        } else if (data < 0x48) {
                    198:                // $40-$47 MSCTRL 信号制御
                    199:                // こいつは頻度が高いのでログレベルを上げておく
                    200:                putlog(3, "Command MSCTRL 制御 %d", (data & 1));
                    201: 
                    202:        } else if (data < 0x50) {
                    203:                // $48-$4f キーデータ送出許可
                    204:                putlog(1, "Command キー送出許可 %d (未実装)", (data & 1));
                    205: 
                    206:        } else if (data < 0x54) {
                    207:                // $50-$53 ディスプレイ制御モード選択
                    208:                // (実装不要)
                    209:                putlog(2, "Command ディスプレイ制御 X68000モード %d", (data & 1));
                    210: 
                    211:        } else if (data < 0x58) {
                    212:                // $54-$57 LED 明るさ選択
                    213:                // 0 が明るく 3 が暗いので、明るさというより暗さ。
                    214:                led_darkness = (data & 3);
                    215:                putlog(1, "Command LED 明るさ %d", led_darkness);
                    216: 
                    217:        } else if (data < 0x5c) {
                    218:                // $58-$5b 本体からのディスプレイ制御許可
                    219:                // (実装不要)
                    220:                putlog(2, "Command 本体からディスプレイ制御 %d", (data & 1));
                    221: 
                    222:        } else if (data < 0x60) {
                    223:                // $5c-$5f OPT.2 によるディスプレイ制御許可
                    224:                // (実装不要)
                    225:                putlog(2, "Command OPT2からディスプレイ制御 %d", (data & 1));
                    226: 
                    227:        } else if (data < 0x70) {
                    228:                // $60-$6f リピートまでの時間
                    229:                rept_delay = 200 + (data & 15) * 100;
                    230:                putlog(1, "Command Repeat Delay %d (%d msec)", (data & 15), rept_delay);
                    231: 
                    232:        } else if (data < 0x80) {
                    233:                // $70-$7f リピート間隔
                    234:                rept_time = 30 + (data & 15) * (data & 15) * 5;
                    235:                putlog(1, "Command Repeat time  %d (%d msec)", (data & 15), rept_time);
                    236: 
                    237:        } else {
                    238:                // $80-$ff LED 制御
                    239:                data &= 0x7f;
                    240:                putlog(1, "Command LED 制御 $%02x", data);
                    241:                uint32 b = 0x01;
                    242:                for (int i = 0; i < led.size(); i++) {
                    243:                        // data は %0 で点灯、led[] は true で点灯
                    244:                        led[i] = ((data & b) == 0);
                    245:                        b <<= 1;
                    246:                }
                    247:        }
                    248: }
                    249: 
1.1       root      250: // キーコード変換表
                    251: // 共通キーコードから X680x0 キーコードに変換する。
                    252: /*static*/ const uint
1.1.1.5 ! root      253: X68030Keyboard::keycode2x68kkey_table[KC_max] = {
1.1       root      254:        NoKey,                                  // [00]
                    255:        X68kKey_BREAK,                  // [01]
                    256:        X68kKey_COPY,                   // [02]
                    257:        X68kKey_romaji,                 // [03]
1.1.1.4   root      258:        X68kKey_code,                   // [04]
1.1       root      259:        X68kKey_kigou,                  // [05]
                    260:        X68kKey_touroku,                // [06]
                    261:        X68kKey_HELP,                   // [07]
                    262:        X68kKey_HOME,                   // [08]
                    263:        X68kKey_TAB,                    // [09]
                    264:        X68kKey_CTRL,                   // [0a]
                    265:        X68kKey_kana,                   // [0b]
                    266:        X68kKey_SHIFT,                  // [0c]
1.1.1.5 ! root      267:        X68kKey_SHIFT,                  // [0d]
1.1       root      268:        X68kKey_CAPS,                   // [0e]
                    269:        NoKey,                                  // [0f]
                    270: 
                    271:        X68kKey_ESC,                    // [10]
                    272:        X68kKey_BS,                             // [11]
                    273:        X68kKey_enter,                  // [12]
                    274:        X68kKey_INS,                    // [13]
                    275:        X68kKey_space,                  // [14]
                    276:        X68kKey_DEL,                    // [15]
                    277:        NoKey,                                  // [16]
                    278:        NoKey,                                  // [17]
                    279:        NoKey,                                  // [18]
                    280:        NoKey,                                  // [19]
                    281:        NoKey,                                  // [1a]
                    282:        NoKey,                                  // [1b]
                    283:        X68kKey_up,                             // [1c]
                    284:        X68kKey_left,                   // [1d]
                    285:        X68kKey_right,                  // [1e]
                    286:        X68kKey_down,                   // [1f]
                    287: 
                    288:        X68kKey_ROLLUP,                 // [20]
                    289:        X68kKey_ROLLDOWN,               // [21]
                    290:        X68kKey_1,                              // [22]
                    291:        X68kKey_2,                              // [23]
                    292:        X68kKey_3,                              // [24]
                    293:        X68kKey_4,                              // [25]
                    294:        X68kKey_5,                              // [26]
                    295:        X68kKey_6,                              // [27]
                    296:        X68kKey_7,                              // [28]
                    297:        X68kKey_8,                              // [29]
                    298:        X68kKey_9,                              // [2a]
                    299:        X68kKey_0,                              // [2b]
                    300:        X68kKey_minus,                  // [2c]
                    301:        X68kKey_circum,                 // [2d]
                    302:        X68kKey_backslash,              // [2e]
                    303:        X68kKey_UNDO,                   // [2f]
                    304: 
                    305:        X68kKey_OPT1,                   // [30]
                    306:        X68kKey_OPT2,                   // [31]
                    307:        X68kKey_Q,                              // [32]
                    308:        X68kKey_W,                              // [33]
                    309:        X68kKey_E,                              // [34]
                    310:        X68kKey_R,                              // [35]
                    311:        X68kKey_T,                              // [36]
                    312:        X68kKey_Y,                              // [37]
                    313:        X68kKey_U,                              // [38]
                    314:        X68kKey_I,                              // [39]
                    315:        X68kKey_O,                              // [3a]
                    316:        X68kKey_P,                              // [3b]
                    317:        X68kKey_at,                             // [3c]
                    318:        X68kKey_bracketleft,    // [3d]
                    319:        X68kKey_hira,                   // [3e]
                    320:        X68kKey_zenkaku,                // [3f]
                    321: 
                    322:        NoKey,                                  // [40]
                    323:        NoKey,                                  // [41]
                    324:        X68kKey_A,                              // [42]
                    325:        X68kKey_S,                              // [43]
                    326:        X68kKey_D,                              // [44]
                    327:        X68kKey_F,                              // [45]
                    328:        X68kKey_G,                              // [46]
                    329:        X68kKey_H,                              // [47]
                    330:        X68kKey_J,                              // [48]
                    331:        X68kKey_K,                              // [49]
                    332:        X68kKey_L,                              // [4a]
                    333:        X68kKey_semicolon,              // [4b]
                    334:        X68kKey_colon,                  // [4c]
                    335:        X68kKey_bracketright,   // [4d]
                    336:        NoKey,                                  // [4e]
                    337:        NoKey,                                  // [4f]
                    338: 
                    339:        NoKey,                                  // [50]
                    340:        NoKey,                                  // [51]
                    341:        X68kKey_Z,                              // [52]
                    342:        X68kKey_X,                              // [53]
                    343:        X68kKey_C,                              // [54]
                    344:        X68kKey_V,                              // [55]
                    345:        X68kKey_B,                              // [56]
1.1.1.5 ! root      346:        X68kKey_N,                              // [57]
        !           347:        X68kKey_M,                              // [58]
1.1       root      348:        X68kKey_comma,                  // [59]
                    349:        X68kKey_period,                 // [5a]
                    350:        X68kKey_slash,                  // [5b]
                    351:        X68kKey_underscore,             // [5c]
                    352:        NoKey,                                  // [5d]
                    353:        NoKey,                                  // [5e]
                    354:        NoKey,                                  // [5f]
                    355: 
                    356:        NoKey,                                  // [60]
                    357:        X68kKey_PAD_plus,               // [61]
                    358:        X68kKey_PAD_minus,              // [62]
                    359:        X68kKey_PAD_7,                  // [63]
                    360:        X68kKey_PAD_8,                  // [64]
                    361:        X68kKey_PAD_9,                  // [65]
                    362:        X68kKey_PAD_4,                  // [66]
                    363:        X68kKey_PAD_5,                  // [67]
                    364:        X68kKey_PAD_6,                  // [68]
                    365:        X68kKey_PAD_1,                  // [69]
                    366:        X68kKey_PAD_2,                  // [6a]
                    367:        X68kKey_PAD_3,                  // [6b]
                    368:        X68kKey_PAD_0,                  // [6c]
                    369:        X68kKey_PAD_decimal,    // [6d]
                    370:        X68kKey_PAD_enter,              // [6e]
                    371:        X68kKey_PAD_CLR,                // [6f]
                    372: 
                    373:        NoKey,                                  // [70]
                    374:        NoKey,                                  // [71]
                    375:        X68kKey_F1,                             // [72]
                    376:        X68kKey_F2,                             // [73]
                    377:        X68kKey_F3,                             // [74]
                    378:        X68kKey_F4,                             // [75]
                    379:        X68kKey_F5,                             // [76]
                    380:        X68kKey_F6,                             // [77]
                    381:        X68kKey_F7,                             // [78]
                    382:        X68kKey_F8,                             // [79]
                    383:        X68kKey_F9,                             // [7a]
                    384:        X68kKey_F10,                    // [7b]
                    385:        X68kKey_PAD_multiply,   // [7c]
                    386:        X68kKey_PAD_divide,             // [7d]
                    387:        X68kKey_PAD_equal,              // [7e]
                    388:        X68kKey_PAD_comma,              // [7f]
                    389: 
                    390:        X68kKey_XF1,                    // [80]
                    391:        X68kKey_XF2,                    // [81]
                    392:        X68kKey_XF3,                    // [82]
                    393:        X68kKey_XF4,                    // [83]
                    394:        X68kKey_XF5,                    // [84]
1.1.1.5 ! root      395:        X68kKey_SHIFT,                  // [85]
1.1       root      396: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.