--- nono/vm/x68kkbd.cpp 2026/04/29 17:05:03 1.1.1.8 +++ nono/vm/x68kkbd.cpp 2026/04/29 17:05:10 1.1.1.10 @@ -4,6 +4,10 @@ // Licensed under nono-license.txt // +// +// X68k キーボード +// + // 送信タイミングについて // キーボードは MFP の USART に繋がっている。 // MFP USART の RR 線 (Receiver Ready) は受信可能なら 'H'、受信中は 'L' に @@ -20,6 +24,7 @@ #include "x68kkbd.h" #include "mfp.h" #include "scc.h" +#include "scheduler.h" #include "sysport.h" // コンストラクタ @@ -27,17 +32,12 @@ X68030Keyboard::X68030Keyboard() { led.resize(7); - rept_event.func = (DeviceCallback_t)&X68030Keyboard::ReptCallback; + rept_event.func = ToEventCallback(&X68030Keyboard::ReptCallback); rept_event.time = 0; - rept_event.SetName("Keyboard Repeat"); + rept_event.Regist("Keyboard Repeat"); - for (int i = 0; i < mouse_event.size(); i++) { - mouse_event[i].dev = this; - mouse_event[i].func = (DeviceCallback_t)&X68030Keyboard::MouseCallback; - // 700us 後から 11bit を 4800 bps の速度で送る - mouse_event[i].time = 700_usec + 1_sec * 11 * (i + 1) / 4800; - mouse_event[i].SetName(string_format("Mouse Data %d", i)); - } + mouse_event.func = ToEventCallback(&X68030Keyboard::MouseCallback); + mouse_event.Regist("Mouse"); } // デストラクタ @@ -45,37 +45,46 @@ X68030Keyboard::~X68030Keyboard() { } -// 本体リセットスイッチによるリセット +// キーボード接続時の MD 固有処理 void -X68030Keyboard::ResetHard() +X68030Keyboard::MDConnect() { - inherited::ResetHard(); - rept_delay = 500_msec; rept_time = 110_msec; rept_key = KC_none; - rept_event.Stop(); + gScheduler->StopEvent(rept_event); - for (int i = 0; i < led.size(); i++) { - led[i] = false; - } led_darkness = 0; - for (int i = 0; i < mouse_event.size(); i++) { - mouse_event[i].Stop(); - } + // XXX マウスの接続取り外しは未定 + gScheduler->StopEvent(mouse_event); + mouse_event.code = 0; } -// 共通キーコードを X680x0 キーコードに変換して返す。 +// キーボード取り外し時の MD 固有処理 +void +X68030Keyboard::MDDisconnect() +{ + gScheduler->StopEvent(rept_event); + gScheduler->StopEvent(mouse_event); + mouse_event.code = 0; +} + +// 共通 keystat を X680x0 キーコードに変換して返す。 // 対応する X680x0 のキーがなければ 0 を返す。 uint -X68030Keyboard::KeyToMDKey(uint keycode) const +X68030Keyboard::KeyToMDKey(uint keystat) const { + uint keycode = KC_CODE(keystat); if (keycode >= countof(keycode2x68kkey_table)) { return 0; } - return keycode2x68kkey_table[keycode]; + uint mdkey = keycode2x68kkey_table[keycode]; + if (mdkey && KC_IS_BREAK(keystat)) { + mdkey |= 0x80; + } + return mdkey; } // シフト状態なら true を返す @@ -125,14 +134,13 @@ X68030Keyboard::KeyInput(uint keystat) // ここでキーリピートのイベント開始処理 if (ismake) { // いま起きているリピートは中止 - rept_event.Stop(); rept_key = keycode; rept_event.time = rept_delay; - rept_event.Start(); + gScheduler->RestartEvent(rept_event); } else { if (keycode == rept_key) { // 同じキーのブレークでのみリピートを終了する - rept_event.Stop(); + gScheduler->StopEvent(rept_event); rept_key = KC_none; } } @@ -142,12 +150,12 @@ void X68030Keyboard::ReptCallback(Event& ev) { // リピート - sendqueue.Enqueue(rept_key); + sendqueue.Enqueue(KeyToMDKey(rept_key)); SendStart(); // 二回目以降のリピートは rept_time 間隔で発生 rept_event.time = rept_time; - rept_event.Start(); + gScheduler->StartEvent(rept_event); } // MFP、システムポートと、キーボードの関係。 @@ -159,11 +167,11 @@ X68030Keyboard::ReptCallback(Event& ev) // <- 本体 || キーボード -> // MFP || // --------+ : || +----- -// | : +--+ || | -// RR|o-------| | || | -// --------+ : | |-----|T0 (Ready) -// +-----| | || | -// Sysport | : +--+ || | +// | : |& || | +// RR|o-------|& || | +// --------+ : |&---------|T0 (Ready) +// +-----|& || | +// Sysport | : |& || | // --------+ | : || | // KeyCtrl|--+ : || +----- // | : || @@ -191,23 +199,17 @@ X68030Keyboard::Ready() if (gSysport->GetKeyCtrl()) { // KEYCTRL が有効なら処理する - // ここで取り出せるのは keystat。 - uint keystat; - if (sendqueue.Dequeue(&keystat)) { + // ここで取り出せるのは MDKey。 + uint x68kkey; + if (sendqueue.Dequeue(&x68kkey)) { // あれば送信 // 呼ばれたからには送信できるはず assert(gMFP->RxIsReady() == true); - uint keycode = KC_CODE(keystat); - // ここで X68k キーコードに変換 (変換できないはずはない) - uint x68kkey = KeyToMDKey(keycode); assert(x68kkey != 0); // 送信 - if (KC_IS_BREAK(keystat)) { - x68kkey |= 0x80; - } gMFP->Rx(x68kkey); } else { // なければ何もせず終了 @@ -239,8 +241,9 @@ X68030Keyboard::MouseSendStart() { uint8 status = 0; - // 最後のバイトを送るまでは、次は受け付けられない - if (mouse_event[2].IsRunning()) { + // 最後のバイトを送るまでは、次は受け付けられない。 + // 送信中かどうかは mouse_event.code で判断している。 + if (mouse_event.code != 0) { return; } @@ -263,23 +266,45 @@ X68030Keyboard::MouseSendStart() status |= mouse_l ? SW_L : 0; status |= mouse_r ? SW_R : 0; - mouse_event[0].code = status; - mouse_event[1].code = mouse_x; - mouse_event[2].code = mouse_y; + // この時点でラッチしてみる(?) + mouse_data[0] = status; + mouse_data[1] = mouse_x; + mouse_data[2] = mouse_y; mouse_x = 0; mouse_y = 0; - mouse_event[0].Start(); - mouse_event[1].Start(); - mouse_event[2].Start(); + // 1バイト目は MSCTRL が立ち下がってから 700us 以上後から送信。 + mouse_event.time = 700_usec; + mouse_event.code = 1; + gScheduler->RestartEvent(mouse_event); } +// マウスデータのイベントコールバック void X68030Keyboard::MouseCallback(Event& ev) { - // LUNA とオブジェクトが違うだけ - gSCC->Rx(1, ev.code); + // マウスは 4800bps で、ストップビット 2 なので11ビット。 + // 1/4800 * 11 = 2.29166 msec なので、1バイトあたり 2.3 msec にしておく。 + + // code は 1 なら1バイト目 ([0]) + // : + // code が 4 なら送らずに終了 + + if (mouse_event.code < 4) { + // 1, 2, 3 バイト目送信 + gSCC->Rx(1, mouse_data[mouse_event.code - 1]); + + // 次のイベント + mouse_event.time = 2300_usec; + mouse_event.code++; + gScheduler->StartEvent(mouse_event); + } else { + // 3 バイト目の送信が終わって、1文字送信分の時間が経過したので + // ここで code を 0 に戻す。 + // XXX 実際のタイミングがどうかは知らない。 + mouse_event.code = 0; + } } // ホストからの制御 @@ -358,7 +383,7 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_kigou, // [05] X68kKey_touroku, // [06] X68kKey_HELP, // [07] - X68kKey_HOME, // [08] + X68kKey_SHIFT, // [08] X68kKey_TAB, // [09] X68kKey_CTRL, // [0a] X68kKey_kana, // [0b] @@ -399,7 +424,7 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_minus, // [2c] X68kKey_circum, // [2d] X68kKey_backslash, // [2e] - X68kKey_UNDO, // [2f] + NoKey, // [2f] X68kKey_OPT1, // [30] X68kKey_OPT2, // [31] @@ -418,8 +443,8 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_hira, // [3e] X68kKey_zenkaku, // [3f] - NoKey, // [40] - NoKey, // [41] + X68kKey_HOME, // [40] + X68kKey_UNDO, // [41] X68kKey_A, // [42] X68kKey_S, // [43] X68kKey_D, // [44] @@ -435,8 +460,8 @@ X68030Keyboard::keycode2x68kkey_table[KC NoKey, // [4e] NoKey, // [4f] - NoKey, // [50] - NoKey, // [51] + X68kKey_XF1, // [50] + X68kKey_XF2, // [51] X68kKey_Z, // [52] X68kKey_X, // [53] X68kKey_C, // [54] @@ -448,9 +473,9 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_period, // [5a] X68kKey_slash, // [5b] X68kKey_underscore, // [5c] - NoKey, // [5d] - NoKey, // [5e] - NoKey, // [5f] + X68kKey_XF3, // [5d] + X68kKey_XF4, // [5e] + X68kKey_XF5, // [5f] NoKey, // [60] X68kKey_PAD_plus, // [61] @@ -485,11 +510,4 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_PAD_divide, // [7d] X68kKey_PAD_equal, // [7e] X68kKey_PAD_comma, // [7f] - - X68kKey_XF1, // [80] - X68kKey_XF2, // [81] - X68kKey_XF3, // [82] - X68kKey_XF4, // [83] - X68kKey_XF5, // [84] - X68kKey_SHIFT, // [85] };