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