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