--- nono/vm/lunakbd.cpp 2026/04/29 17:04:29 1.1.1.2 +++ nono/vm/lunakbd.cpp 2026/04/29 17:04:50 1.1.1.8 @@ -1,6 +1,7 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // // キーボードとマウス @@ -14,15 +15,15 @@ // ということにする。 #include "lunakbd.h" -#include "mystring.h" #include "sio.h" // コンストラクタ LunaKeyboard::LunaKeyboard() { - monitor.Init(30, 1); + monitor_size = nnSize(30, 1); memset(reptable, 0, sizeof(reptable)); + led.resize(2); key_event.dev = this; key_event.func = (DeviceCallback_t)&LunaKeyboard::KeyboardCallback; @@ -39,7 +40,7 @@ LunaKeyboard::LunaKeyboard() for (int i = 1; i < 3; i++) { mouse_event[i].dev = this; mouse_event[i].func = (DeviceCallback_t)&LunaKeyboard::MouseCallback; - mouse_event[i].time = 0; + mouse_event[i].time = 2_msec * i; mouse_event[i].SetName(string_format("Mouse Slot%d", i)); } } @@ -53,13 +54,19 @@ LunaKeyboard::~LunaKeyboard() void LunaKeyboard::ResetHard() { - // マウスサンプリングは電源オン時は有効らしい - gScheduler->AddEvent(&mouse_event[0]); + // 動作中のタイマーは一旦とめる + key_event.Stop(); + for (int i = 0; i < countof(mouse_event); i++) { + mouse_event[i].Stop(); + } + + // で、マウスサンプリングは電源オン時から有効らしい + mouse_event[0].Start(); } // モニター -bool -LunaKeyboard::MonitorUpdate() +void +LunaKeyboard::MonitorUpdate(TextScreen& monitor) { int x, y; monitor.Clear(); @@ -79,8 +86,19 @@ LunaKeyboard::MonitorUpdate() (mouse_l ? 'L' : '-'), (mouse_m ? 'M' : '-'), (mouse_r ? 'R' : '-')); +} + +// LUNA キーコードから LED 番号を返す。LED キーでなければ -1 を返す。 +int +LunaKeyboard::LunaKey2LED(uint lunakey) const +{ + // 2つしかないのでこのくらいでいいか + if (lunakey == LunaKey_kana) + return 0; + if (lunakey == LunaKey_CAPS) + return 1; - return true; + return -1; } // キーを押した @@ -102,11 +120,18 @@ LunaKeyboard::MakeKey(uint keycode) return; } + // LED はトグル? + int n = LunaKey2LED(lunakey); + if (n >= 0) { + led[n] = !led[n]; + } + // キーが押された putlog(1, "MakeKey %d(%s)", lunakey, keyname[lunakey]); reptable[lunakey] = 1; // イベントを登録 + // (LED キーの自動 Break はイベントコールバック側で処理する) SetKeyEvent(lunakey); } @@ -124,6 +149,18 @@ LunaKeyboard::BreakKey(uint keycode) return; } + // LED キーはここでは処理しない (MakeKey() で処理してある) + if (LunaKey2LED(lunakey) >= 0) { + return; + } + + BreakKeyCommon(lunakey); +} + +// キーを離した (通常キーと LED キーの場合の両方から呼ばれる) +void +LunaKeyboard::BreakKeyCommon(uint lunakey) +{ // キーが離された putlog(2, "BreakKey %d(%s)", lunakey, keyname[lunakey]); reptable[lunakey] = 0; @@ -136,7 +173,7 @@ LunaKeyboard::BreakKey(uint keycode) void LunaKeyboard::SetKeyEvent(uint code) { - uint64 now = gScheduler->GetVirtTime(); + uint64 now = gMPU->GetVirtTime(); // t は現在の仮想時刻に対応するスロット uint64 t = (now / 2_msec) % 10; @@ -159,7 +196,7 @@ LunaKeyboard::SetKeyEvent(uint code) key_sending = true; key_event.time = target - now; key_event.code = code; - gScheduler->AddEvent(&key_event); + key_event.Start(); } } @@ -180,16 +217,23 @@ LunaKeyboard::MouseInput(int x, int y, b // キー入力コールバック // SIO に送信するタイミングで呼ばれる。 void -LunaKeyboard::KeyboardCallback(int code) +LunaKeyboard::KeyboardCallback(Event& ev) { + int& code = ev.code; + gSIO->Rx(1, code); key_sending = false; + + // かなと CAP キーの押下なら、続けてキーの復旧も送る。 + if (LunaKey2LED(code) >= 0) { + BreakKeyCommon(code); + } } // マウスサンプリングコールバック // 20msec ごとに呼ばれる。 void -LunaKeyboard::MouseSamplingCallback(int arg) +LunaKeyboard::MouseSamplingCallback(Event& ev) { int reset_x = 0; int reset_y = 0; @@ -211,6 +255,12 @@ LunaKeyboard::MouseSamplingCallback(int mouse_l != prev_l || mouse_m != prev_m) { + putlog(2, "Mouse Sampling x=%d y=%d %c%c%c", + mouse_x, mouse_y, + (mouse_r ? 'L' : '-'), + (mouse_m ? 'M' : '-'), + (mouse_l ? 'R' : '-')); + // 1バイト目、ボタン状態。 // mouse_[rlm] 変数は押し下げが true、LUNA のマウスは押し下げが %0 uint8 b = 0x80 | @@ -233,15 +283,15 @@ LunaKeyboard::MouseSamplingCallback(int // 1バイト目はここで送信 gSIO->Rx(1, b); - // 2バイト目は 2msec 秒後に予約 - mouse_event[1].time = 2_msec; + // 2バイト目は 2msec 秒後に送信 mouse_event[1].code = (uint8)mouse_x; - gScheduler->AddEvent(&mouse_event[1]); + mouse_event[1].Start(); - // 3バイト目は 4msec 秒後に予約 - mouse_event[2].time = 4_msec; + // 3バイト目は 4msec 秒後に送信 mouse_event[2].code = (uint8)mouse_y; - gScheduler->AddEvent(&mouse_event[2]); + mouse_event[2].Start(); + } else { + putlog(3, "Mouse Sampling inactive"); } // 積算リセット @@ -252,15 +302,20 @@ LunaKeyboard::MouseSamplingCallback(int prev_m = mouse_m; // 20msec 後に再び自分を呼び出す - mouse_event[0].time = 20_msec; - gScheduler->AddEvent(&mouse_event[0]); + ev.Start(); } // マウスの後続バイトを送出するイベントコールバック void -LunaKeyboard::MouseCallback(int code) +LunaKeyboard::MouseCallback(Event& ev) +{ + gSIO->Rx(1, ev.code); +} + +// ホストからの制御 +void +LunaKeyboard::Command(uint32 data) { - gSIO->Rx(1, code); } // 共通キーコードを LUNA キーコードに変換して返す。