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