|
|
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.4 ! root 7: #include "keyboard.h"
1.1 root 8: #include "mfp.h"
1.1.1.4 ! root 9: #include "mpu680x0.h"
1.1 root 10: #include "mystring.h"
11: #include "scheduler.h"
12:
1.1.1.3 root 13: std::unique_ptr<MFPDevice> gMFP;
1.1 root 14:
15: // コンストラクタ
16: MFPDevice::MFPDevice()
17: {
18: logname = "mfp";
19: devname = "MFP";
20: devaddr = baseaddr;
21: devlen = 0x2000;
22: monitor.Init(65, 17);
23:
24: for (int ch = 0; ch < countof(event); ch++) {
25: event[ch].dev = this;
26: event[ch].func = (DeviceCallback_t)&MFPDevice::TimerCallback;
27: event[ch].code = ch;
1.1.1.2 root 28: event[ch].SetName(string_format("MFP Timer-%c", ch + 'A'));
1.1 root 29: }
1.1.1.4 ! root 30:
! 31: // キーボード周りは x68kkbd.cpp のコメント参照
! 32: key_event.dev = this;
! 33: key_event.func = (DeviceCallback_t)&MFPDevice::KeyCallback;
! 34: key_event.time = 3750_usec;
! 35: key_event.SetName("MFP USART");
1.1 root 36: }
37:
38: // デストラクタ
39: MFPDevice::~MFPDevice()
40: {
41: }
42:
43: // MPU の RESET 命令によるリセット
44: void
45: MFPDevice::ResetSoft()
46: {
47: // TxDR, UDR, TSR はクリアされない
48:
49: // ?
50: mfp.tsr = 0x80;
51:
52: // それ以外のすべてのレジスタはクリア?
53: mfp.vr = 0;
54:
55: // タイマーはすべてストップなのでイベントを削除
56: for (int ch = 0; ch < countof(event); ch++) {
1.1.1.3 root 57: event[ch].Stop();
1.1 root 58: }
1.1.1.4 ! root 59: key_event.Stop();
1.1 root 60:
1.1.1.4 ! root 61: // 信号線
! 62: rr = false;
1.1.1.3 root 63:
1.1.1.4 ! root 64: // ペンディング割り込みクリア
1.1.1.3 root 65: }
66:
1.1 root 67: uint64
1.1.1.4 ! root 68: MFPDevice::Read(uint32 addr)
1.1 root 69: {
70: uint8 data;
71:
1.1.1.4 ! root 72: switch (addr) {
1.1 root 73: case MFP::GPIP:
74: data = mfp.gpip;
75: break;
76: case MFP::AER:
77: data = mfp.aer;
78: break;
79: case MFP::DDR:
80: data = mfp.ddr;
81: break;
82: case MFP::IERA:
83: data = mfp.ier.a;
84: break;
85: case MFP::IERB:
86: data = mfp.ier.b;
87: break;
88: case MFP::IPRA:
89: data = mfp.ipr.a;
90: break;
91: case MFP::IPRB:
92: data = mfp.ipr.b;
93: break;
94: case MFP::ISRA:
95: data = mfp.isr.a;
96: break;
97: case MFP::ISRB:
98: data = mfp.isr.b;
99: break;
100: case MFP::IMRA:
101: data = mfp.imr.a;
102: break;
103: case MFP::IMRB:
104: data = mfp.imr.b;
105: break;
106: case MFP::VR:
107: data = mfp.vr;
108: break;
109: case MFP::TACR:
110: data = mfp.tcr[0];
111: break;
112: case MFP::TBCR:
113: data = mfp.tcr[1];
114: break;
115: case MFP::TCDCR:
116: data = (mfp.tcr[2] << 4) | mfp.tcr[3];
117: break;
118: case MFP::TADR:
119: data = GetTDR(0);
120: break;
121: case MFP::TBDR:
122: data = GetTDR(1);
123: break;
124: case MFP::TCDR:
125: data = GetTDR(2);
126: break;
127: case MFP::TDDR:
128: data = GetTDR(3);
129: break;
130: case MFP::SCR:
131: data = mfp.scr;
132: break;
133: case MFP::UCR:
134: data = mfp.ucr;
135: break;
136: case MFP::RSR:
137: data = mfp.rsr;
138: break;
139: case MFP::TSR:
140: data = mfp.tsr;
141: break;
142: case MFP::UDR:
143: data = mfp.udr;
144: break;
1.1.1.4 ! root 145: default:
! 146: data = 0xff;
! 147: break;
1.1 root 148: }
149: return data;
150: }
151:
152: uint64
1.1.1.4 ! root 153: MFPDevice::Write(uint32 addr, uint32 data)
1.1 root 154: {
1.1.1.4 ! root 155: switch (addr) {
1.1 root 156: case MFP::GPIP:
157: putlog(0, "GPIP <- $%02x 未実装書き込み", data);
158: mfp.gpip = data;
159: break;
160: case MFP::AER:
161: putlog(0, "AER <- $%02x 未実装書き込み", data);
162: mfp.aer = data;
163: break;
164: case MFP::DDR:
165: if (data != 0) {
166: putlog(0, "DDR <- $%02x 未実装書き込み", data);
167: }
168: mfp.ddr = data;
169: break;
170: case MFP::IERA:
171: putlog(2, "IERA <- $%02x", data);
172: mfp.ier.a = data;
173: break;
174: case MFP::IERB:
175: putlog(2, "IERB <- $%02x", data);
176: mfp.ier.b = data;
177: break;
178: case MFP::IPRA:
179: putlog(2, "IPRA <- $%02x", data);
180: mfp.ipr.a = data;
181: break;
182: case MFP::IPRB:
183: putlog(2, "IPRB <- $%02x", data);
184: mfp.ipr.b = data;
185: break;
186: case MFP::ISRA:
187: putlog(2, "ISRA <- $%02x", data);
188: mfp.isr.a = data;
189: break;
190: case MFP::ISRB:
191: putlog(2, "ISRB <- $%02x", data);
192: mfp.isr.b = data;
193: break;
194: case MFP::IMRA:
195: putlog(2, "IMRA <- $%02x", data);
196: mfp.imr.a = data;
197: break;
198: case MFP::IMRB:
199: putlog(2, "IMRB <- $%02x", data);
200: mfp.imr.b = data;
201: break;
202: case MFP::VR:
203: mfp.vr = data & 0xf0;
204: putlog(2, "VR <- $%02x", mfp.vr);
205: break;
206: case MFP::TACR:
207: putlog(2, "TACR <- $%02x", data);
208: SetTCR(0, data);
209: break;
210: case MFP::TBCR:
211: putlog(2, "TBCR <- $%02x", data);
212: SetTCR(1, data);
213: break;
214: case MFP::TCDCR:
215: putlog(2, "TCDCR <- $%02x", data);
216: SetTCR(2, data >> 4);
217: SetTCR(3, data & 7);
218: break;
219: case MFP::TADR:
220: putlog(2, "TADR <- $%02x", data);
221: SetTDR(0, data);
222: break;
223: case MFP::TBDR:
224: putlog(2, "TBDR <- $%02x", data);
225: SetTDR(1, data);
226: break;
227: case MFP::TCDR:
228: putlog(2, "TCDR <- $%02x", data);
229: SetTDR(2, data);
230: break;
231: case MFP::TDDR:
232: putlog(2, "TDDR <- $%02x", data);
233: SetTDR(3, data);
234: break;
235: case MFP::SCR:
236: putlog(0, "SCR <- $%02x 未実装書き込み", data);
237: mfp.scr = data;
238: break;
239: case MFP::UCR:
1.1.1.4 ! root 240: putlog(2, "UCR <- $%02x", data);
! 241: SetUCR(data);
1.1 root 242: break;
243: case MFP::RSR:
1.1.1.4 ! root 244: putlog(2, "RSR <- $%02x", data);
! 245: SetRSR(data);
1.1 root 246: break;
247: case MFP::TSR:
248: putlog(0, "TSR <- $%02x 未実装書き込み", data);
249: mfp.tsr = (mfp.tsr & 0xf0) | (data & 0x0f);
250: break;
251: case MFP::UDR:
1.1.1.4 ! root 252: if (data == 0x40 || data == 0x41) {
! 253: // MSCTRL だけ頻度が高いのでログレベルを上げておく
! 254: putlog(3, "UDR <- $%02x", data);
! 255: } else {
! 256: putlog(2, "UDR <- $%02x", data);
! 257: }
! 258: SetUDR(data);
! 259: break;
! 260: default:
1.1 root 261: break;
262: }
263: return 0;
264: }
265:
266: uint64
1.1.1.4 ! root 267: MFPDevice::Peek(uint32 addr)
1.1 root 268: {
269: uint8 data;
270:
1.1.1.4 ! root 271: switch (addr) {
1.1 root 272: case MFP::GPIP:
273: data = mfp.gpip;
274: break;
275: case MFP::AER:
276: data = mfp.aer;
277: break;
278: case MFP::DDR:
279: data = mfp.ddr;
280: break;
281: case MFP::IERA:
282: data = mfp.ier.a;
283: break;
284: case MFP::IERB:
285: data = mfp.ier.b;
286: break;
287: case MFP::IPRA:
288: data = mfp.ipr.a;
289: break;
290: case MFP::IPRB:
291: data = mfp.ipr.b;
292: break;
293: case MFP::ISRA:
294: data = mfp.isr.a;
295: break;
296: case MFP::ISRB:
297: data = mfp.isr.b;
298: break;
299: case MFP::IMRA:
300: data = mfp.imr.a;
301: break;
302: case MFP::IMRB:
303: data = mfp.imr.b;
304: break;
305: case MFP::VR:
306: data = mfp.vr;
307: break;
308: case MFP::TACR:
309: data = mfp.tcr[0];
310: break;
311: case MFP::TBCR:
312: data = mfp.tcr[1];
313: break;
314: case MFP::TCDCR:
315: data = (mfp.tcr[2] << 4) | mfp.tcr[3];
316: break;
317: case MFP::TADR:
318: data = GetTDR(0);
319: break;
320: case MFP::TBDR:
321: data = GetTDR(1);
322: break;
323: case MFP::TCDR:
324: data = GetTDR(2);
325: break;
326: case MFP::TDDR:
327: data = GetTDR(3);
328: break;
329: case MFP::SCR:
330: data = mfp.scr;
331: break;
332: case MFP::UCR:
333: data = mfp.ucr;
334: break;
335: case MFP::RSR:
336: data = mfp.rsr;
337: break;
338: case MFP::TSR:
339: data = mfp.tsr;
340: break;
341: case MFP::UDR:
342: data = mfp.udr;
343: break;
1.1.1.4 ! root 344: default:
! 345: data = 0xff;
1.1 root 346: }
347: return data;
348: }
349:
350: bool
351: MFPDevice::MonitorUpdate()
352: {
353: int x;
354: int y;
355:
356: monitor.Clear();
357:
358: // 0 1 2 3 4 5 6
359: // 012345678901234567890123456789012345678901234567890123456789012345
360: // IER IMR IPR ISR Mode TDR Cnt
361: // An:MPSC TxEmpty Enable Mask Pend Serv Timer-A Delay(50us) 255 255
362:
363: // 割り込み関連
364: monitor.Print(0, 0, " %-12s %-6s %-4s %-4s %-4s",
365: "", "IER", "IMR", "IPR", "ISR");
366: y = 1;
367: for (int i = 15; i >= 0; i--, y++) {
368: uint16 mask = (1 << i);
369: monitor.Print(0, y, "%c%d:%-12s %-6s %-4s %-4s %-4s",
370: i >= 8 ? 'A' : 'B',
371: (i % 8),
372: intrname[i],
373: (mfp.ier.w & mask) ? "Enable" : "",
374: (mfp.imr.w & mask) ? "" : "Mask", // %0 でマスクする
375: (mfp.ipr.w & mask) ? "Pend" : "",
376: (mfp.isr.w & mask) ? "Serv" : "");
377: }
378:
379: // タイマー関連
380: x = 39;
381: y = 1;
382: for (int ch = 0; ch < 4; ch++) {
383: y = ch + 1;
384: monitor.Print(x, y, "Timer-%c", ch + 'A');
385: if (mfp.tcr[ch] == 0) {
386: monitor.Print(x + 8, y, "Stopped");
387: } else if (mfp.tcr[ch] == 8) {
388: monitor.Print(x + 8, y, "Event");
389: } else if (mfp.tcr[ch] > 8) {
390: monitor.Print(x + 8, y, "Pulse(%s)", prescale_str[mfp.tcr[ch] - 8]);
391: } else {
392: monitor.Print(x + 8, y, "Delay(%s)", prescale_str[mfp.tcr[ch]]);
393: }
394:
395: monitor.Print(x + 19, y, "%3d", GetTDR(ch));
396: monitor.Print(x + 23, y, "%3d", mfp.tdr[ch]);
397: }
398:
399: // GPIP 関連
400: x = 39;
401: y = 8;
1.1.1.4 ! root 402: monitor.Puts(x, y++, "GPIP Name GPIP AER DDR");
1.1 root 403: for (int i = 7; i >= 0; i--, y++) {
404: uint mask = (1 << i);
405: monitor.Print(x, y, "b%d %-6s %d %d %s", i, gpipname[i],
406: (mfp.gpip & mask) ? 1 : 0,
407: (mfp.aer & mask) ? 1 : 0,
408: (mfp.ddr & mask) ? "OUT" : "IN");
409: }
410:
411: return true;
412: }
413:
414: /*static*/ const char *
415: MFPDevice::intrname[] = {
416: "RTC Alarm",
417: "EXPON",
418: "POW SW",
419: "FM IRQ",
420: "Timer-D",
421: "Timer-C",
422: "V-Disp",
423: "---",
424: "Timer-B",
425: "MPSC TxErr",
426: "MPSC TxEmpty",
427: "MPSC RxErr",
428: "MPSC RxFull",
429: "Timer-A",
430: "CRTC IRQ",
431: "H-Sync",
432: };
433:
434: /*static*/ const char *
435: MFPDevice::gpipname[] = {
436: "ALARM",
437: "EXPON",
438: "POW SW",
439: "FMIRQ",
440: "V-Disp",
441: "------",
442: "CIRQ",
443: "H-Sync",
444: };
445:
446: // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す
447: /*static*/ const int
448: MFPDevice::prescale_ns[8] = {
449: 0,
450: 1000, // /4
451: 2500, // /10
452: 4000, // /16
453: 12500, // /50
454: 16000, // /64
455: 25000, // /100
456: 50000, // /200
457: };
458:
459: /*static*/ const char *
460: MFPDevice::prescale_str[8] = {
461: "",
462: "1us",
463: "2.5us",
464: "4us",
465: "12.5us",
466: "16us",
467: "25us",
468: "50us",
469: };
470:
471: // タイマーのチャンネルからベクタ(ビット番号) に変換する
472: /*static*/ const int
1.1.1.4 ! root 473: MFPDevice::timer_vector[4] = {
! 474: MFP::INTR_TIMER_A,
! 475: MFP::INTR_TIMER_B,
! 476: MFP::INTR_TIMER_C,
! 477: MFP::INTR_TIMER_D,
! 478: };
1.1 root 479:
480: // このタイマーで割り込みを上げる必要があるかどうかを返す
481: bool
482: MFPDevice::IsTimerIntrEnable(uint ch) const
483: {
1.1.1.3 root 484: assertmsg(ch < 4, "ch=%u", ch);
1.1 root 485: __assume(ch < 4);
486:
487: // 割り込みが無効なら false
488: if ((mfp.ier.w & (1 << timer_vector[ch])) == 0) {
489: return false;
490: }
491:
492: // 割り込みがマスクされていれば false
493: if ((mfp.imr.w & (1 << timer_vector[ch])) == 0) {
494: return false;
495: }
496:
497: // そうでなければ、割り込みを上げる必要がある
498: return true;
499: }
500:
501: // TxCR をセットする
502: void
503: MFPDevice::SetTCR(int ch, uint32 data)
504: {
505: uint32 prev;
506:
507: prev = mfp.tcr[ch];
508: data &= 0x0f;
509:
510: mfp.tcr[ch] = data;
511: if (mfp.tcr[ch] > 0x08) {
512: putlog(0, "T%cCR サポートしていないモード $%02x",
513: ch + 'A', mfp.tcr[ch]);
514: return;
515: }
516: if (mfp.tcr[ch] == 8) {
517: // イベントカウントモード
518:
519: // TDR をロードする
520: mfp.initial_tdr[ch] = mfp.tdr[ch];
521: putlog(1, "Timer-%c イベントカウントモード", ch + 'A');
522: return;
523:
524: } else if (mfp.tcr[ch] == 0) {
525: // タイマー停止
526: if (prev != 0) {
527: putlog(1, "Timer-%c 停止", ch + 'A');
528: }
529: mfp.timer_start[ch] = 0;
1.1.1.3 root 530: event[ch].Stop();
1.1 root 531: return;
532:
533: } else {
534: // タイマー開始
535: int scale = prescale_ns[mfp.tcr[ch]];
536: if (prev == 0) {
537: // タイマー停止中に開始
538: // ここで initial_tdr にロード
539: mfp.initial_tdr[ch] = mfp.tdr[ch] ?: 256;
540: mfp.timer_start[ch] = gScheduler->GetVirtTime();
541: } else {
542: // タイマー動作中に(再)開始
543:
544: // タイマー動作中に TxCR に書き込むと、TxDR は影響を受けずに、
545: // プリスケーラのカウンタがリセットされる。
546: // 例えば、TCR = 0x01 (プリスケール 10)、TDR = 0x05 で、
547: // プリスケールカウントが12回進行した時点で TCR に再び 0x01
548: // (プリスケール10) が書き込まれた場合、以下のようになるはず。
549: //
550: // time ->
551: // prescale cnt| 0 1 2 3 4 5 6 7 8 9 0 1 2
552: // main count | 5 ----------------> 4 -->
553: // * ここで TCR 書き込み
554: // TCR書き込み後のprescale cnt | 0 1 2 3 4 5 6 7 8 9 0 1
555: // TCR書き込み後のmain count | 4 ----------------> 3 ->
556: uint64 ellapsed;
557: uint deccount;
558:
559: // タイマー開始時からの経過時間
560: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch];
561:
562: // タイマー開始時から今までのメインカウンタ減算回数
563: deccount = ellapsed / scale;
564:
565: // 再設定
566: mfp.initial_tdr[ch] -= deccount;
567: mfp.timer_start[ch] += gScheduler->GetVirtTime();
568: }
569:
570: // 割り込みを上げる必要があれば、カウントダウン終了時にイベントを
571: // 起こす。
572: // 割り込みを上げる必要がない場合は、TxDR を読み出す時に正しい値が
573: // 算出できるだけでよくて、それは timer_start 等により行えているので
574: // 他には何もしなくてよい。Timer-B 対策。
575: if (IsTimerIntrEnable(ch)) {
576: event[ch].time = mfp.initial_tdr[ch] * scale;
1.1.1.3 root 577: event[ch].Start();
1.1 root 578: }
579:
580: putlog(1, "Timer-%c ディレイモード開始(%d.%d x %d usec)",
581: ch + 'A',
582: scale / 1000,
583: (scale / 100) % 10,
584: mfp.initial_tdr[ch]);
585: }
586: }
587:
588: // TxDR の読み出し
589: // タイマーデータレジスタの現在値は保持しておらず、
590: // タイマー開始時刻と減算量が分かっているので読み出しのたびに求める。
591: // この操作に副作用はないので Peek/Monitor でも使用可能。
592: uint8
1.1.1.3 root 593: MFPDevice::GetTDR(int ch) const
1.1 root 594: {
595: uint64 ellapsed;
596: uint64 count;
597: uint32 data;
598:
599: // イベントカウントモードなら initial_tdr が読める?
600: if (mfp.tcr[ch] == 8) {
601: return mfp.initial_tdr[ch];
602: }
603:
604: // タイマー停止中なら TxDR と同じでよい?
605: if (mfp.tcr[ch] == 0) {
606: return mfp.tdr[ch];
607: }
608:
609: // タイマー開始時からの経過時間
610: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch];
611:
612: // タイマー開始時から現在までのメインカウンタ減算回数
613: count = ellapsed / prescale_ns[mfp.tcr[ch]];
614:
615: // カウント終了時に割り込みが上がる設定になっていれば
616: // count は必ず 0 から initail_tdr-1 までの範囲だが、
617: // カウント終了時に割り込みが上がる設定になっていない場合は
618: // 経過時間とそれに伴い count はひたすら増える。
619: // そのため initial_tdr で modulo する。
620: count %= mfp.initial_tdr[ch];
621:
622: // count は減算回数だが、
623: // TxDR レジスタの読み出し値は減算カウンタの現在値。
624: // TxDR = 10 で開始して count = 0 のうちは TxDR 読み出しは 10。
625: // TxDR = 10 で開始して count = 1 のうちは TxDR 読み出しは 9。
626: // :
627: // TxDR = 10 で開始して count = 9 のうちは TxDR 読み出しは 1。
628: data = mfp.initial_tdr[ch] - count;
629:
630: return data;
631: }
632:
633: // TxDR への書き込み
634: void
635: MFPDevice::SetTDR(int ch, uint32 data)
636: {
637: uint64 ellapsed;
638: uint64 scale;
639: uint64 period;
640: uint64 timer_end;
641:
642: mfp.tdr[ch] = data;
643:
644: // イベントカウントモードなら即ロード
645: if (mfp.tcr[ch] == 8) {
646: mfp.initial_tdr[ch] = mfp.tdr[ch];
647: }
648:
649: // カウント終了時に割り込みが上がる設定になっていれば、
650: // そのイベントコールバックで tdr を initial_tdr にロードするが、
651: // 割り込みが上がらない設定の場合、そのままでは tdr をリロードする
652: // 機会がない。そのためこのケースでは書き込み時点の次のカウント終了
653: // 時にイベントを起こす必要がある。
654: //
655: // TCR=1(プリスケール10)、TDR=5 で 38カウント目に TDR がセットされた
656: // 場合、ここから 12カウント目がリロードタイミング。
657: //
658: // pre | 0 ... 0 ... 0 ... 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
659: // main| 5 --> 4 --> 3 --> 2 ------------->*
660: // |<--------------------->|
661: // イベントを起こすまでの時間
662: if (IsTimerIntrEnable(ch) == false) {
663: // タイマー開始時から現在までの経過時間
664: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch];
665: // プリスケールカウント時間 (上でいう1カウントの時間)
666: scale = prescale_ns[mfp.tcr[ch]];
1.1.1.3 root 667: if (__predict_true(scale > 0)) {
668: // 1タイマー期間(上でいう50カウントに相当する時間)
669: period = scale * mfp.initial_tdr[ch];
670: // タイマー開始時から次のタイムアップ時刻までの時間
671: timer_end = ((ellapsed + period - 1) / period) * period;
672: // タイムアップ時刻
673: timer_end = mfp.timer_start[ch] + timer_end;
674: } else {
675: // タイムアップ時刻
676: timer_end = mfp.timer_start[ch];
677: }
1.1 root 678: // 現在から次のタイムアップ時刻まで
679: event[ch].time = timer_end - gScheduler->GetVirtTime();
1.1.1.3 root 680: event[ch].Start();
1.1 root 681:
682: putlog(3, "Timer-%c TDR 更新予約 %d.%09d", ch + 'A',
683: (int)(event[ch].time / (1000 * 1000 * 1000)),
684: (int)(event[ch].time % (1000 * 1000 * 1000)));
685: }
686: }
687:
688: // イベントコールバック
689: void
690: MFPDevice::TimerCallback(int arg)
691: {
692: int ch = arg;
693: int prevtdr;
694: uint64 ellapsed;
695: uint64 scale;
696: uint64 period;
697: uint64 timer_end;
698:
699: // タイムアップした時刻を計算。現在時刻ではない。
700: // 現在時刻はタイムアップした直後の命令境界の時刻なので。
701:
702: // タイマー開始時から現在までの経過時間
703: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch];
704: // 1プリスケール期間
705: scale = prescale_ns[mfp.tcr[ch]];
706: // 1タイマー期間
707: period = scale * mfp.initial_tdr[ch];
708: // タイマー開始時から直近のタイムアップ時刻まで
709: timer_end = (ellapsed / period) * period;
710:
711: // TxDR がゼロになったので TxDR をリロード
712: prevtdr = mfp.initial_tdr[ch];
713: mfp.initial_tdr[ch] = mfp.tdr[ch] ?: 256;
714: // 今タイムアップ時刻を次のタイマー起点に更新
715: mfp.timer_start[ch] += timer_end;
716:
717: // 割り込み有効なら
718: if (IsTimerIntrEnable(ch)) {
719: // 1タイマー期間を新しい TDR で再計算
720: period = prescale_ns[mfp.tcr[ch]] * mfp.initial_tdr[ch];
721: // イベント再設定
722: event[ch].time = period;
1.1.1.3 root 723: event[ch].Start();
1.1 root 724:
725: // 割り込みを上げる
1.1.1.4 ! root 726: gMPU680x0->Interrupt(this, 6, mfp.vr + timer_vector[ch]);
1.1 root 727: }
728:
729: if (mfp.initial_tdr[ch] != prevtdr) {
730: putlog(1, "Timer-%c ディレイモード更新(%u.%u x %u usec)",
731: ch + 'A',
732: (uint)(scale / 1000),
733: (uint)((scale / 100) % 10),
734: (uint)mfp.initial_tdr[ch]);
735: }
736: }
737:
738: // VDisp 入力
739: void
740: MFPDevice::SetVDisp(bool vdisp)
741: {
742: // TAI への入力はイベントカウントモードの時のみ
743: if (mfp.tcr[0] == 8) {
744: // AER が示す方向と同じエッジ方向の時
745: bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP));
746: if (aer == vdisp) {
747: // カウンタを減算
748: mfp.initial_tdr[0]--;
749: if (mfp.initial_tdr[0] == 0) {
750: // 0 になったらリロード
751: mfp.initial_tdr[0] = mfp.tdr[0];
752:
753: // XXX ここで割り込みを上げる
754: }
755: }
756: }
757:
758: // GPIP への入力
759: SetGPIP(MFP::GPIP_VDISP, vdisp);
760: }
761:
762: // GPIP への入力。
763: // num はビット番号(0..7)。
764: void
765: MFPDevice::SetGPIP(int num, bool val)
766: {
767: bool aer = (mfp.aer & (1 << num));
768: bool old = (mfp.gpip & (1 << num));
769:
770: // 立ち上がりか立ち下がりで割り込みを上げる (AER による)
771: // AER OLD VAL Interrupt
772: // 0 0 0 0
773: // 0 0 1 0
774: // 0 1 0 1
775: // 0 1 1 0
776: // 1 0 0 0
777: // 1 0 1 1
778: // 1 1 0 0
779: // 1 1 1 0
1.1.1.3 root 780: if ((old != val) && (aer == val)) {
1.1 root 781: // XXX ここで割り込みを上げる
782: }
783:
784: if (val) {
785: mfp.gpip |= (1 << num);
786: } else {
787: mfp.gpip &= ~(1 << num);
788: }
789: }
1.1.1.4 ! root 790:
! 791: // UCR への書き込み
! 792: void
! 793: MFPDevice::SetUCR(uint32 data)
! 794: {
! 795: mfp.ucr = data;
! 796:
! 797: if ((mfp.ucr & MFP::UCR_CLK) == 0) {
! 798: putlog(0, "UCR CLK=0 未実装");
! 799: }
! 800: if (((mfp.ucr & MFP::UCR_WL) >> 5) != 0) {
! 801: putlog(0, "UCR WL=%d 未実装", (mfp.ucr >> 5) & 3);
! 802: }
! 803: if (((mfp.ucr & MFP::UCR_ST) >> 3) != 1) {
! 804: putlog(0, "UCR ST=%d 未実装", (mfp.ucr >> 3) & 3);
! 805: }
! 806: }
! 807:
! 808: // RSR への書き込み
! 809: void
! 810: MFPDevice::SetRSR(uint32 data)
! 811: {
! 812: uint32 old = mfp.rsr;
! 813:
! 814: mfp.rsr = data;
! 815:
! 816: if ((old & MFP::RSR_RE) == 0 && (mfp.rsr & MFP::RSR_RE)) {
! 817: // RE 0 -> 1
! 818: rr = true;
! 819: }
! 820: if ((old & MFP::RSR_RE) && (mfp.rsr & MFP::RSR_RE) == 0) {
! 821: // RE 1 -> 0
! 822: rr = false;
! 823: mfp.rsr &= 0x0f; // 上位4ビットのステータスを %0 に
! 824: }
! 825: }
! 826:
! 827: // UDR への書き込み
! 828: void
! 829: MFPDevice::SetUDR(uint32 data)
! 830: {
! 831: if ((mfp.tsr & MFP::TSR_TE)) {
! 832: gKeyboard->Command(data);
! 833: }
! 834: }
! 835:
! 836: // システムポート#4 の KEY CTRL の状態を受け取る。
! 837: void
! 838: MFPDevice::SetKeyCtrl(bool val)
! 839: {
! 840: key_ctrl = val;
! 841: putlog(1, "KEYCTRL = %d", key_ctrl);
! 842: }
! 843:
! 844: // RR (Receiver Ready) 線の状態を返す。true なら Ready。
! 845: // これはシステムポート#4 の KEY CTRL の状態も加味したもの。
! 846: bool
! 847: MFPDevice::IsRR() const
! 848: {
! 849: return rr && key_ctrl;
! 850: }
! 851:
! 852: // キーボードからデータを受信
! 853: void
! 854: MFPDevice::Rx(uint32 data)
! 855: {
! 856: // Ready を下げる
! 857: rr = false;
! 858:
! 859: key_event.code = data;
! 860: key_event.Start();
! 861: }
! 862:
! 863: // キーボードからのデータが受信し終わった頃に呼ばれるイベント。
! 864: void
! 865: MFPDevice::KeyCallback(int code)
! 866: {
! 867: // Ready を元に戻す
! 868: rr = true;
! 869:
! 870: mfp.udr = code;
! 871: mfp.rsr |= MFP::RSR_BF;
! 872:
! 873: // XXX この辺要再考察
! 874: mfp.isr.a |= 0x10;
! 875: // 割り込み有効でマスクされてない時だけ
! 876: if ((mfp.ier.a & 0x10) && (mfp.imr.a & 0x10)) {
! 877: gMPU680x0->Interrupt(this, 6, mfp.vr + MFP::INTR_RXFULL);
! 878: }
! 879: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.