--- nono/vm/x68kkbd.cpp 2026/04/29 17:05:07 1.1.1.9 +++ 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,25 +45,29 @@ 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; +} + +// キーボード取り外し時の MD 固有処理 +void +X68030Keyboard::MDDisconnect() +{ + gScheduler->StopEvent(rept_event); + gScheduler->StopEvent(mouse_event); + mouse_event.code = 0; } // 共通 keystat を X680x0 キーコードに変換して返す。 @@ -130,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; } } @@ -152,7 +155,7 @@ X68030Keyboard::ReptCallback(Event& ev) // 二回目以降のリピートは rept_time 間隔で発生 rept_event.time = rept_time; - rept_event.Start(); + gScheduler->StartEvent(rept_event); } // MFP、システムポートと、キーボードの関係。 @@ -164,11 +167,11 @@ X68030Keyboard::ReptCallback(Event& ev) // <- 本体 || キーボード -> // MFP || // --------+ : || +----- -// | : +--+ || | -// RR|o-------| | || | -// --------+ : | |-----|T0 (Ready) -// +-----| | || | -// Sysport | : +--+ || | +// | : |& || | +// RR|o-------|& || | +// --------+ : |&---------|T0 (Ready) +// +-----|& || | +// Sysport | : |& || | // --------+ | : || | // KeyCtrl|--+ : || +----- // | : || @@ -238,8 +241,9 @@ X68030Keyboard::MouseSendStart() { uint8 status = 0; - // 最後のバイトを送るまでは、次は受け付けられない - if (mouse_event[2].IsRunning()) { + // 最後のバイトを送るまでは、次は受け付けられない。 + // 送信中かどうかは mouse_event.code で判断している。 + if (mouse_event.code != 0) { return; } @@ -262,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; + } } // ホストからの制御