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

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

unix.superglobalmegacorp.com

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