|
|
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.2 root 7: // キーボードとマウス
8: //
9: // キーボード/マウスからシリアルポートへの入力は、1バイトの送信自体に約1msec
10: // (9600bps、スタートビット1、ストップビット1) で送信後に 1msec 空けるそう
11: // なので、ここでは単純に 2msec を1スロットとする。
12: // マウスは 20msec ごとにサンプリングして連続する3バイトを送り、
13: // キーボードは任意のスロットで 1バイト送ってくるので、概念的には
14: // 10スロットのうち 0, 1, 2 をマウスが、3..9 をキーボードが使用する
15: // ということにする。
16:
1.1 root 17: #include "lunakbd.h"
1.1.1.2 root 18: #include "mystring.h"
1.1 root 19: #include "sio.h"
20:
21: // コンストラクタ
22: LunaKeyboard::LunaKeyboard()
23: {
1.1.1.5 root 24: monitor_size = nnSize(30, 1);
1.1.1.2 root 25:
1.1 root 26: memset(reptable, 0, sizeof(reptable));
1.1.1.4 root 27: led.resize(2);
1.1 root 28:
1.1.1.2 root 29: key_event.dev = this;
30: key_event.func = (DeviceCallback_t)&LunaKeyboard::KeyboardCallback;
31: key_event.time = 0;
32: key_event.SetName("KeyInput");
33:
34: // マウスイベント#0 はサンプリング用も兼ねているので常にオン
35: mouse_event[0].dev = this;
36: mouse_event[0].func =
37: (DeviceCallback_t)&LunaKeyboard::MouseSamplingCallback;
38: mouse_event[0].time = 20_msec;
39: mouse_event[0].SetName("Mouse Sampling");
40:
41: for (int i = 1; i < 3; i++) {
42: mouse_event[i].dev = this;
43: mouse_event[i].func = (DeviceCallback_t)&LunaKeyboard::MouseCallback;
1.1.1.6 ! root 44: mouse_event[i].time = 2_msec * i;
1.1.1.2 root 45: mouse_event[i].SetName(string_format("Mouse Slot%d", i));
46: }
1.1 root 47: }
48:
49: // デストラクタ
50: LunaKeyboard::~LunaKeyboard()
51: {
52: }
53:
1.1.1.2 root 54: // リセット
55: void
56: LunaKeyboard::ResetHard()
57: {
1.1.1.6 ! root 58: // 動作中のタイマーは一旦とめる
! 59: key_event.Stop();
! 60: for (int i = 0; i < countof(mouse_event); i++) {
! 61: mouse_event[i].Stop();
! 62: }
! 63:
! 64: // で、マウスサンプリングは電源オン時から有効らしい
1.1.1.3 root 65: mouse_event[0].Start();
1.1.1.2 root 66: }
67:
68: // モニター
1.1.1.5 root 69: void
70: LunaKeyboard::MonitorUpdate(TextScreen& monitor)
1.1.1.2 root 71: {
72: int x, y;
73: monitor.Clear();
74:
75: x = mouse_x;
76: y = mouse_y;
77: if (x < -999)
78: x = -999;
79: if (x > 999)
80: x = 999;
81: if (y < -999)
82: y = -999;
83: if (y > 999)
84: y = 999;
85: monitor.Print(0, 0, "Mouse: x=%-4d y=%-4d %c %c %c",
86: x, y,
87: (mouse_l ? 'L' : '-'),
88: (mouse_m ? 'M' : '-'),
89: (mouse_r ? 'R' : '-'));
90: }
91:
1.1.1.4 root 92: // LUNA キーコードから LED 番号を返す。LED キーでなければ -1 を返す。
93: int
94: LunaKeyboard::LunaKey2LED(uint lunakey) const
95: {
96: // 2つしかないのでこのくらいでいいか
97: if (lunakey == LunaKey_kana)
98: return 0;
99: if (lunakey == LunaKey_CAPS)
100: return 1;
101:
102: return -1;
103: }
104:
1.1 root 105: // キーを押した
106: void
107: LunaKeyboard::MakeKey(uint keycode)
108: {
109: uint lunakey;
110:
111: // 共通キーコードから LUNA キーコードに
112: lunakey = keycode2lunakey(keycode);
113:
114: // LUNA にないキーは無視
115: if (lunakey == NoKey) {
116: return;
117: }
118:
119: // すでにこのキーが押されていれば送らない
120: if (reptable[lunakey]) {
121: return;
122: }
123:
1.1.1.4 root 124: // LED はトグル?
125: int n = LunaKey2LED(lunakey);
126: if (n >= 0) {
127: led[n] = !led[n];
128: }
129:
1.1 root 130: // キーが押された
131: putlog(1, "MakeKey %d(%s)", lunakey, keyname[lunakey]);
132: reptable[lunakey] = 1;
133:
1.1.1.2 root 134: // イベントを登録
1.1.1.4 root 135: // (LED キーの自動 Break はイベントコールバック側で処理する)
1.1.1.2 root 136: SetKeyEvent(lunakey);
1.1 root 137: }
138:
139: // キーを離した
140: void
141: LunaKeyboard::BreakKey(uint keycode)
142: {
143: uint lunakey;
144:
145: // 共通キーコードから LUNA キーコードに
146: lunakey = keycode2lunakey(keycode);
147:
148: // LUNA にないキーは無視
149: if (lunakey == NoKey) {
150: return;
151: }
152:
1.1.1.4 root 153: // LED キーはここでは処理しない (MakeKey() で処理してある)
154: if (LunaKey2LED(lunakey) >= 0) {
155: return;
156: }
157:
158: BreakKeyCommon(lunakey);
159: }
160:
161: // キーを離した (通常キーと LED キーの場合の両方から呼ばれる)
162: void
163: LunaKeyboard::BreakKeyCommon(uint lunakey)
164: {
1.1 root 165: // キーが離された
166: putlog(2, "BreakKey %d(%s)", lunakey, keyname[lunakey]);
167: reptable[lunakey] = 0;
168:
1.1.1.2 root 169: // イベントを登録
170: SetKeyEvent(lunakey | 0x80);
171: }
172:
173: // キー入力用の空きスロットにイベントをセット
174: void
175: LunaKeyboard::SetKeyEvent(uint code)
176: {
177: uint64 now = gScheduler->GetVirtTime();
178:
179: // t は現在の仮想時刻に対応するスロット
180: uint64 t = (now / 2_msec) % 10;
181: // n はその次のスロット
182: uint64 n = (t + 1) % 10;
183:
184: // マウススロットなら避ける
185: if (n < 3)
186: n = 3;
187:
188: // このイベントが起きる時間を再計算
189: uint64 target = (now / 20_msec) * 20_msec + n * 2_msec;
190: if (n < t) {
191: // n が折り返している場合は n は次の20msec 枠内
192: target += 20_msec;
193: }
194:
195: // イベントを登録。
196: if (key_sending == false) {
197: key_sending = true;
198: key_event.time = target - now;
199: key_event.code = code;
1.1.1.3 root 200: key_event.Start();
1.1.1.2 root 201: }
202: }
203:
204: // マウス入力
205: void
206: LunaKeyboard::MouseInput(int x, int y, bool rb, bool lb, bool mb)
207: {
208: // ホストからマウスイベントのたびに呼ばれるので、ここで積算。
209: // 20msec ごとのサンプリングのタイミングで積算結果を処理する。
210: // LUNA のマウスの Y 方向は上に動く方向がプラスなので、ホスト入力とは逆。
211: mouse_x += x;
212: mouse_y -= y;
213: mouse_r = rb;
214: mouse_l = lb;
215: mouse_m = mb;
216: }
217:
218: // キー入力コールバック
219: // SIO に送信するタイミングで呼ばれる。
220: void
1.1.1.6 ! root 221: LunaKeyboard::KeyboardCallback(Event& ev)
1.1.1.2 root 222: {
1.1.1.6 ! root 223: int& code = ev.code;
! 224:
1.1.1.2 root 225: gSIO->Rx(1, code);
226: key_sending = false;
1.1.1.4 root 227:
228: // かなと CAP キーの押下なら、続けてキーの復旧も送る。
229: if (LunaKey2LED(code) >= 0) {
230: BreakKeyCommon(code);
231: }
1.1.1.2 root 232: }
233:
234: // マウスサンプリングコールバック
235: // 20msec ごとに呼ばれる。
236: void
1.1.1.6 ! root 237: LunaKeyboard::MouseSamplingCallback(Event& ev)
1.1.1.2 root 238: {
239: int reset_x = 0;
240: int reset_y = 0;
241:
242: // 移動量±1は送信しないが次回に向けた積算は続けるそうだ。
243: if (mouse_x == -1 || mouse_x == 1) {
244: reset_x = mouse_x;
245: mouse_x = 0;
246: }
247: if (mouse_y == -1 || mouse_y == 1) {
248: reset_y = mouse_y;
249: mouse_y = 0;
250: }
251:
252: // 移動量が±1 を超えるかボタンがどれかでも変化すれば送信。
253: if (mouse_x != 0 ||
254: mouse_y != 0 ||
255: mouse_r != prev_r ||
256: mouse_l != prev_l ||
257: mouse_m != prev_m)
258: {
1.1.1.3 root 259: putlog(2, "Mouse Sampling x=%d y=%d %c%c%c",
260: mouse_x, mouse_y,
261: (mouse_r ? 'L' : '-'),
262: (mouse_m ? 'M' : '-'),
263: (mouse_l ? 'R' : '-'));
264:
1.1.1.2 root 265: // 1バイト目、ボタン状態。
266: // mouse_[rlm] 変数は押し下げが true、LUNA のマウスは押し下げが %0
267: uint8 b = 0x80 |
268: (mouse_l ? 0 : 0x04) |
269: (mouse_m ? 0 : 0x02) |
270: (mouse_r ? 0 : 0x01);
271:
272: // 2バイト目が X、3バイト目が Y。
273: // 移動量は絶対値 0x7f でサチる (signed char ではない)。
274: if (mouse_x < -127)
275: mouse_x = -127;
276: if (mouse_x > 127)
277: mouse_x = 127;
278:
279: if (mouse_y < -127)
280: mouse_y = -127;
281: if (mouse_y > 127)
282: mouse_y = 127;
283:
284: // 1バイト目はここで送信
285: gSIO->Rx(1, b);
286:
1.1.1.6 ! root 287: // 2バイト目は 2msec 秒後に送信
1.1.1.2 root 288: mouse_event[1].code = (uint8)mouse_x;
1.1.1.3 root 289: mouse_event[1].Start();
1.1.1.2 root 290:
1.1.1.6 ! root 291: // 3バイト目は 4msec 秒後に送信
1.1.1.2 root 292: mouse_event[2].code = (uint8)mouse_y;
1.1.1.3 root 293: mouse_event[2].Start();
294: } else {
295: putlog(3, "Mouse Sampling inactive");
1.1.1.2 root 296: }
297:
298: // 積算リセット
299: mouse_x = reset_x;
300: mouse_y = reset_y;
301: prev_r = mouse_r;
302: prev_l = mouse_l;
303: prev_m = mouse_m;
304:
305: // 20msec 後に再び自分を呼び出す
1.1.1.6 ! root 306: ev.Start();
1.1.1.2 root 307: }
308:
309: // マウスの後続バイトを送出するイベントコールバック
310: void
1.1.1.6 ! root 311: LunaKeyboard::MouseCallback(Event& ev)
1.1.1.2 root 312: {
1.1.1.6 ! root 313: gSIO->Rx(1, ev.code);
1.1 root 314: }
315:
1.1.1.4 root 316: // ホストからの制御
317: void
318: LunaKeyboard::Command(uint32 data)
319: {
320: }
321:
1.1 root 322: // 共通キーコードを LUNA キーコードに変換して返す。
323: // LUNA キーがなければ NoKey を返す。
324: uint
325: LunaKeyboard::keycode2lunakey(uint keycode)
326: {
327: if (keycode >= countof(keycode2lunakey_table)) {
328: return NoKey;
329: }
330:
331: return keycode2lunakey_table[keycode];
332: }
333:
334: // キーコード変換表
335: // 共通キーコードから LUNA キーコードに変換する。
336: // ぶっちゃけた話共通キーコードは LUNA キーコードをベースにしているので、
337: // 穴がある以外は全部透過。
338: /*static*/ const uint
339: LunaKeyboard::keycode2lunakey_table[128] = {
340: NoKey, // [00]
341: NoKey, // [01]
342: NoKey, // [02]
343: NoKey, // [03]
344: NoKey, // [04]
345: NoKey, // [05]
346: NoKey, // [06]
347: NoKey, // [07]
348: NoKey, // [08]
349: LunaKey_TAB, // [09]
350: LunaKey_CTRL, // [0a]
351: LunaKey_kana, // [0b]
352: LunaKey_SHIFT_L, // [0c]
353: LunaKey_SHIFT_R, // [0d]
354: LunaKey_CAPS, // [0e]
355: LunaKey_SF, // [0f]
356:
357: LunaKey_ESC, // [10]
358: LunaKey_BS, // [11]
359: LunaKey_enter, // [12]
360: NoKey, // [13]
361: LunaKey_space, // [14]
362: LunaKey_DEL, // [15]
363: LunaKey_XFER, // [16]
364: LunaKey_VALID, // [17]
365: LunaKey_PF11, // [18]
366: LunaKey_PF12, // [19]
367: LunaKey_PF13, // [1a]
368: LunaKey_PF14, // [1b]
369: LunaKey_up, // [1c]
370: LunaKey_left, // [1d]
371: LunaKey_right, // [1e]
372: LunaKey_down, // [1f]
373:
374: NoKey, // [20]
375: NoKey, // [21]
376: LunaKey_1, // [22]
377: LunaKey_2, // [23]
378: LunaKey_3, // [24]
379: LunaKey_4, // [25]
380: LunaKey_5, // [26]
381: LunaKey_6, // [27]
382: LunaKey_7, // [28]
383: LunaKey_8, // [29]
384: LunaKey_9, // [2a]
385: LunaKey_0, // [2b]
386: LunaKey_minus, // [2c]
387: LunaKey_circum, // [2d]
388: LunaKey_backslash, // [2e]
389: NoKey, // [2f]
390:
391: NoKey, // [30]
392: NoKey, // [31]
393: LunaKey_Q, // [32]
394: LunaKey_W, // [33]
395: LunaKey_E, // [34]
396: LunaKey_R, // [35]
397: LunaKey_T, // [36]
398: LunaKey_Y, // [37]
399: LunaKey_U, // [38]
400: LunaKey_I, // [39]
401: LunaKey_O, // [3a]
402: LunaKey_P, // [3b]
403: LunaKey_at, // [3c]
404: LunaKey_bracketleft, // [3d]
405: NoKey, // [3e]
406: NoKey, // [3f]
407:
408: NoKey, // [40]
409: NoKey, // [41]
410: LunaKey_A, // [42]
411: LunaKey_S, // [43]
412: LunaKey_D, // [44]
413: LunaKey_F, // [45]
414: LunaKey_G, // [46]
415: LunaKey_H, // [47]
416: LunaKey_J, // [48]
417: LunaKey_K, // [49]
418: LunaKey_L, // [4a]
419: LunaKey_semicolon, // [4b]
420: LunaKey_colon, // [4c]
421: LunaKey_bracketright, // [4d]
422: NoKey, // [4e]
423: NoKey, // [4f]
424:
425: NoKey, // [50]
426: NoKey, // [51]
427: LunaKey_Z, // [52]
428: LunaKey_X, // [53]
429: LunaKey_C, // [54]
430: LunaKey_V, // [55]
431: LunaKey_B, // [56]
432: LunaKey_N, // [57]
433: LunaKey_M, // [58]
434: LunaKey_comma, // [59]
435: LunaKey_period, // [5a]
436: LunaKey_slash, // [5b]
437: LunaKey_underscore, // [5c]
438: NoKey, // [5d]
439: NoKey, // [5e]
440: NoKey, // [5f]
441:
442: NoKey, // [60]
443: LunaKey_PAD_plus, // [61]
444: LunaKey_PAD_minus, // [62]
445: LunaKey_PAD_7, // [63]
446: LunaKey_PAD_8, // [64]
447: LunaKey_PAD_9, // [65]
448: LunaKey_PAD_4, // [66]
449: LunaKey_PAD_5, // [67]
450: LunaKey_PAD_6, // [68]
451: LunaKey_PAD_1, // [69]
452: LunaKey_PAD_2, // [6a]
453: LunaKey_PAD_3, // [6b]
454: LunaKey_PAD_0, // [6c]
455: LunaKey_PAD_decimal, // [6d]
456: LunaKey_PAD_enter, // [6e]
457: NoKey, // [6f]
458:
459: NoKey, // [70]
460: NoKey, // [71]
461: LunaKey_F1, // [72]
462: LunaKey_F2, // [73]
463: LunaKey_F3, // [74]
464: LunaKey_F4, // [75]
465: LunaKey_F5, // [76]
466: LunaKey_F6, // [77]
467: LunaKey_F7, // [78]
468: LunaKey_F8, // [79]
469: LunaKey_F9, // [7a]
470: LunaKey_F10, // [7b]
471: LunaKey_PAD_multiply, // [7c]
472: LunaKey_PAD_divide, // [7d]
473: LunaKey_PAD_equal, // [7e]
474: LunaKey_PAD_comma, // [7f]
475: };
476:
477: /*static*/ const char * const
478: LunaKeyboard::keyname[] =
479: {
480: "", // 00
481: "", // 01
482: "", // 02
483: "", // 03
484: "", // 04
485: "", // 05
486: "", // 06
487: "", // 07
488: "", // 08
489: "TAB", // 09
490: "CTRL", // 0a
491: "かな", // 0b
492: "SHIFT", // 0c
493: "SHIFT", // 0d
494: "CAPS", // 0e
495: "S.F", // 0f
496:
497: "ESC", // 10
498: "BS", // 11
499: "Enter", // 12
500: "", // 13
501: "Space", // 14
502: "DEL", // 15
503: "XFER", // 16
504: "VALID", // 17
505: "PF11", // 18
506: "PF12", // 19
507: "PF13", // 1a
508: "PF14", // 1b
509: "↑", // 1c
510: "←", // 1d
511: "→", // 1e
512: "↓", // 1f
513:
514: "", // 20
515: "", // 21
516: "1!", // 22
517: "2\"", // 23
518: "3#", // 24
519: "4$", // 25
520: "5%", // 26
521: "6&", // 27
522: "7'", // 28
523: "8(", // 29
524: "9)", // 2a
525: "0", // 2b
526: "-=", // 2c
527: "^~", // 2d
528: "\\|", // 2e
529: "", // 2f
530:
531: "", // 30
532: "", // 31
533: "Q", // 32
534: "W", // 33
535: "E", // 34
536: "R", // 35
537: "T", // 36
538: "Y", // 37
539: "U", // 38
540: "I", // 39
541: "O", // 3a
542: "P", // 3b
543: "@`", // 3c
544: "[{", // 3d
545: "", // 3e
546: "", // 3f
547:
548: "", // 40
549: "", // 41
550: "A", // 42
551: "S", // 43
552: "D", // 44
553: "F", // 45
554: "G", // 46
555: "H", // 47
556: "J", // 48
557: "K", // 49
558: "L", // 4a
559: ";+", // 4b
560: ":*", // 4c
561: "]}", // 4d
562: "", // 4e
563: "", // 4f
564:
565: "", // 50
566: "", // 51
567: "Z", // 52
568: "X", // 53
569: "C", // 54
570: "V", // 55
571: "B", // 56
572: "N", // 57
573: "M", // 58
574: ",<", // 59
575: ".>", // 5a
576: "/?", // 5b
577: " _", // 5c
578: "", // 5d
579: "", // 5e
580: "", // 5f
581:
582: "", // 60
583: "PAD+", // 61
584: "PAD-", // 62
585: "PAD7", // 63
586: "PAD8", // 64
587: "PAD9", // 65
588: "PAD4", // 66
589: "PAD5", // 67
590: "PAD6", // 68
591: "PAD1", // 69
592: "PAD2", // 6a
593: "PAD3", // 6b
594: "PAD0", // 6c
595: "PAD.", // 6d
596: "PADEn", // 6e
597: "", // 6f
598:
599: "", // 70
600: "", // 71
601: "F1", // 72
602: "F2", // 73
603: "F3", // 74
604: "F4", // 75
605: "F5", // 76
606: "F6", // 77
607: "F7", // 78
608: "F8", // 79
609: "F9", // 7a
610: "F10", // 7b
611: "PAD*", // 7c
612: "PAD/", // 7d
613: "PAD=", // 7e
614: "PAD,", // 7f
615: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.