|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "upd7201.h"
1.1.1.5 root 8: #include "interrupt.h"
1.1 root 9:
10: // コンストラクタ
1.1.1.7 ! root 11: uPD7201Device::uPD7201Device(const std::string& objname_)
! 12: : inherited(objname_)
1.1 root 13: {
14: cr.chan[0].id = 0;
15: cr.chan[0].name = "A";
16: cr.chan[1].id = 1;
17: cr.chan[1].name = "B";
18:
19: cr.chan[0].desc = NULL;
20: cr.chan[1].desc = NULL;
1.1.1.7 ! root 21:
! 22: monitor.func = (MonitorCallback_t)&uPD7201Device::MonitorUpdate;
! 23: monitor.SetSize(48, 22);
! 24: // 登録は継承先で行う。機種ごとに通りのいい名前を使い分けているため。
1.1 root 25: }
26:
27: // デストラクタ
28: uPD7201Device::~uPD7201Device()
29: {
30: }
31:
32: // リセット
33: void
1.1.1.6 root 34: uPD7201Device::ResetHard()
1.1 root 35: {
36: putlog(2, "リセット");
37:
38: // CR2A はチップリセットで bit6 以外を '0' に
39: cr.cr2a &= ~0xbf;
40:
41: // チャンネルリセット
42: ResetChannel(&cr.chan[0]);
43: ResetChannel(&cr.chan[1]);
44: }
45:
46: // チャンネルリセット
47: void
48: uPD7201Device::ResetChannel(struct SIO::channel *chan)
49: {
1.1.1.5 root 50: putlog(2, "Channel %s Reset", chan->name);
1.1 root 51:
1.1.1.5 root 52: // CR0 b2-0 (PTR)
1.1 root 53: chan->ptr = 0;
54:
55: // CR1 b0,1,3,4,7
56: chan->cr1 &= ~(SIO::CR1_WAIT_EN | SIO::CR1_RXINT |
57: SIO::CR1_TXINT_EN | SIO::CR1_ESINT_EN);
1.1.1.5 root 58: chan->all_or_first = false;
1.1 root 59:
60: // CR3 b0-7
61: chan->cr3 = 0;
62:
63: // CR5 b1,2,3,4,7
64: chan->cr5 &= ~(SIO::CR5_DTR | SIO::CR5_SENDBREAK | SIO::CR5_TX_EN |
65: SIO::CR5_CRC16 | SIO::CR5_RTS);
66:
67: // SR0 は b0,1 が '0'、b2,6 が '1'、残りは不定
68: chan->sr0 &= ~(SIO::SR0_INTPEND | SIO::SR0_RXAVAIL);
69: chan->sr0 |= (SIO::SR0_TXUNDER | SIO::SR0_TXEMPTY);
70:
71: // SR1 は b4-7 が '0'
72: chan->sr1 &= ~(SIO::SR1_ENDOFFRAME | SIO::SR1_CRCERROR |
73: SIO::SR1_RXOVERRUN | SIO::SR1_PARITYERROR);
74:
1.1.1.5 root 75: // 内部状態をリセット
1.1 root 76: chan->es_ratched = false;
1.1.1.5 root 77: chan->reset_txint_pend = true;
1.1 root 78:
79: // 受信バッファをクリア
80: memset(chan->rxbuf, 0, sizeof(chan->rxbuf));
81: chan->rxlen = 0;
82: }
83:
84: // 制御ポートの読み込み
85: uint8
86: uPD7201Device::ReadCtrl(struct SIO::channel *chan)
87: {
88: uint8 data;
89:
90: switch (chan->ptr) {
91: case 0: // SR0
1.1.1.5 root 92: data = chan->sr0;
1.1 root 93: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
94: // アクセス後は SR0 へ戻す
95: chan->ptr = 0;
96: break;
97:
98: case 1: // SR1
1.1.1.5 root 99: data = chan->sr1;
1.1 root 100: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
101: // アクセス後は SR0 へ戻す
102: chan->ptr = 0;
103: break;
104:
105: case 2:
106: // SR2B はベクタの読み出し
107: if (chan->id == 1) {
108: data = cr.vector;
109: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
110: // アクセス後は SR0 へ戻す
111: chan->ptr = 0;
112: break;
113: }
114:
115: // SR2A はない
116: FALLTHROUGH;
117:
118: default:
119: putlog(0, "未実装レジスタ読み込み SR%d%s",
120: chan->ptr, chan->name);
121: // SR0 へ戻る?
122: chan->ptr = 0;
123: return 0xff;
124: }
125: return data;
126: }
127:
128: // 制御ポートの書き込み
129: void
130: uPD7201Device::WriteCtrl(struct SIO::channel *chan, uint32 data)
131: {
1.1.1.5 root 132: // CR0 はコマンドかまたは次にアクセスするレジスタを指定する。
133: // CR0 以外のレジスタをアクセスすると、次のアクセスは CR0 に戻る。
1.1 root 134:
1.1.1.5 root 135: if (chan->ptr == 0) {
136: WriteCR0(chan, data);
137: } else {
138: switch (chan->ptr) {
139: case 1:
140: WriteCR1(chan, data);
1.1 root 141: break;
1.1.1.5 root 142: case 2:
143: WriteCR2(chan, data);
1.1 root 144: break;
1.1.1.5 root 145: case 3:
146: WriteCR3(chan, data);
1.1 root 147: break;
1.1.1.5 root 148: case 4:
149: WriteCR4(chan, data);
1.1 root 150: break;
1.1.1.5 root 151: case 5:
152: WriteCR5(chan, data);
1.1 root 153: break;
1.1.1.5 root 154: case 6:
155: WriteCR6(chan, data);
1.1 root 156: break;
1.1.1.5 root 157: case 7:
158: WriteCR7(chan, data);
1.1 root 159: break;
160: default:
1.1.1.5 root 161: putlog(0, "未実装レジスタ書き込み CR%d%s <- $%02x",
162: chan->ptr, chan->name, data);
163: break;
1.1 root 164: }
165: // アクセス後は CR0 へ戻す
166: chan->ptr = 0;
167: }
168: }
169:
1.1.1.2 root 170: // 制御ポートの Peek
171: uint8
172: uPD7201Device::PeekCtrl(const struct SIO::channel *chan) const
173: {
174: switch (chan->ptr) {
175: case 0: // SR0
1.1.1.5 root 176: return chan->sr0;
1.1.1.2 root 177:
178: case 1: // SR1
1.1.1.5 root 179: return chan->sr1;
1.1.1.2 root 180:
181: case 2: // SR2
182: // SR2A はない。SR2B はベクタの読み出し
183: if (chan->id == 1) {
184: return cr.vector;
185: }
186: FALLTHROUGH;
187:
188: default:
189: // 未調査
190: return 0xff;
191: }
192: }
193:
1.1.1.5 root 194: // CR0 への書き込み
195: void
196: uPD7201Device::WriteCR0(struct SIO::channel *chan, uint32 data)
1.1.1.2 root 197: {
1.1.1.5 root 198: uint cmd;
1.1.1.2 root 199:
1.1.1.5 root 200: // XXX b7,b6 は未対応。
201: // b5,b4,b3 がコマンド。
202: // b2,b1,b0 が次にアクセスするレジスタ(chan->ptr)の切り替え。
203: chan->cr0 = data;
204: chan->ptr = (chan->cr0 & SIO::CR0_PTR);
205:
206: cmd = (chan->cr0 & SIO::CR0_CMD) >> 3;
207: if (cmd == 0) {
208: // コマンド0 ならレジスタ切り替え
209: putlog(3, "CR0%s <- $%02x (ptr=%d)", chan->name, data, chan->ptr);
210: } else {
211: // 0 以外ならコマンド発行
212: putlog(2, "CR0%s <- $%02x", chan->name, data);
213: }
214: switch (cmd) {
215: case 0: // No operation
216: break;
217: case 1: // Send Abort
218: if (chan->mode == SIO::Mode::HDLC) {
219: putlog(0, "CR0: Send Abort 未実装");
220: } else {
221: // XXX Send Abort コマンドは「HDLC モードのみ有効」と書いて
222: // あるがそれ以外の時にどうなるか不明。
223: putlog(0, "CR0: 未定義コマンド %d", cmd);
224: }
225: break;
226: case 2: // Reset External/Status Interrupt
227: putlog(3, "CR0%s: Reset E/S Interrupt", chan->name);
228: chan->es_ratched = false;
229: break;
230: case 3: // Channel Reset
231: ResetChannel(chan);
232: break;
233: case 4: // Enable Interrupt On Next Receive Character
234: putlog(0, "CR0: 未実装コマンド %d", cmd);
235: break;
236: case 5: // Reset Transmitter Interrupt/DMA Pending
237: putlog(1, "CR0%s: Reset Tx Int/DMA Pending", chan->name);
238: chan->reset_txint_pend = false;
239: ChangeInterrupt();
240: break;
241: case 6: // Error Reset
242: case 7: // End of Interrupt
243: putlog(0, "CR0: 未実装コマンド %d", cmd);
244: break;
245: default:
246: __unreachable();
1.1.1.2 root 247: }
248: }
249:
1.1.1.5 root 250: // CR1 への書き込み
251: void
252: uPD7201Device::WriteCR1(struct SIO::channel *chan, uint32 data)
1.1.1.2 root 253: {
1.1.1.5 root 254: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
255:
256: chan->cr1 = data;
257:
258: // RXINT モードで all_or_first の値(初期値)を用意。
259: // DISABLE なら(使わないのでどっちでもいいはずだけど一応) false にしとく。
260: // FIRSTCHAR なら初期状態が true。ALL_* なら常時 true。
261: chan->all_or_first = ((chan->cr1 & SIO::CR1_RXINT) != SIO::RXINT_DISABLE);
1.1.1.2 root 262: }
263:
1.1.1.5 root 264: // CR2 への書き込み
265: void
266: uPD7201Device::WriteCR2(struct SIO::channel *chan, uint32 data)
267: {
268: if (chan->id == 0) { // CR2A
269: putlog(2, "CR2A <- $%02x 書き込み(b7,b2-0未実装)", data);
270: cr.cr2a = data;
271: } else { // CR2B
272: putlog(2, "CR2B <- $%02x (Set vector)", data);
273: cr.vector = data;
274: }
275: }
276:
277: // CR3 への書き込み
278: void
279: uPD7201Device::WriteCR3(struct SIO::channel *chan, uint32 data)
280: {
281: chan->cr3 = data;
282:
283: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
284: putlog(1, "Channel %s RX %s, %dbits",
285: chan->name,
286: (chan->cr3 & SIO::CR3_RX_EN) ? "Enable" : "Disable",
287: bits_per_char[(chan->cr3 & SIO::CR3_RXBITS) >> 6]);
288: }
289:
290: // CR4 への書き込み
291: void
292: uPD7201Device::WriteCR4(struct SIO::channel *chan, uint32 data)
293: {
294: chan->cr4 = data;
295: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
296: uint8 stopbits = (chan->cr4 & SIO::CR4_STOPBITS);
297: uint8 syncmode = (chan->cr4 & SIO::CR4_SYNCMODE);
298:
299: // モード分け、優先順位は分からない
300: if (stopbits == SIO::SYNC_MODE) {
301: if (syncmode == SIO::SYNC_HDLC) {
302: chan->mode = SIO::Mode::HDLC;
303: putlog(2, "Channel %s HDLC Mode", chan->name);
304: } else {
305: chan->mode = SIO::Mode::SYNC;
306: const char *sm[] = { "8bit", "16bit", "HDLC?", "Ext" };
307: putlog(2, "Channel %s Sync (%s) Mode",
308: chan->name, sm[syncmode >> 4]);
309: }
310: } else {
311: chan->mode = SIO::Mode::ASYNC;
312: const char *cm[] = { "x1", "x16", "x32", "x64" };
313: const char *sm[] = { "?", "1", "1.5", "2" };
314: putlog(2, "Channel %s Async (%s clock, stopbit %s) Mode",
315: chan->name,
316: cm[(chan->cr4 & SIO::CR4_CLKRATE) >> 6],
317: sm[stopbits >> 2]);
318: }
319: }
320:
321: // CR5 への書き込み
322: void
323: uPD7201Device::WriteCR5(struct SIO::channel *chan, uint32 data)
324: {
325: chan->cr5 = data;
326:
327: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
328: putlog(1, "Channel %s TX %s, %dbits",
329: chan->name,
330: (chan->cr5 & SIO::CR5_TX_EN) ? "Enable" : "Disable",
331: bits_per_char[(chan->cr5 & SIO::CR5_TXBITS) >> 5]);
332: }
333:
334: // CR6 への書き込み
335: void
336: uPD7201Device::WriteCR6(struct SIO::channel *chan, uint32 data)
337: {
338: chan->cr6 = data;
339:
340: putlog(0, "CR6%s <- $%02x 書き込み(未実装)", chan->name, data);
341: }
342:
343: // CR7 への書き込み
344: void
345: uPD7201Device::WriteCR7(struct SIO::channel *chan, uint32 data)
346: {
347: chan->cr7 = data;
348:
349: putlog(0, "CR7%s <- $%02x 書き込み(未実装)", chan->name, data);
350: }
1.1.1.2 root 351:
1.1 root 352: // データポートの読み込み
353: uint8
1.1.1.2 root 354: uPD7201Device::ReadData(struct SIO::channel *chan)
1.1 root 355: {
356: uint8 data;
357:
358: if (chan->rxlen > 0) {
359: data = chan->rxbuf[0];
1.1.1.5 root 360: putlog(3, "Ch%s Data -> $%02x", chan->name, data);
1.1 root 361: chan->rxlen--;
1.1.1.5 root 362: if (chan->rxlen == 0) {
363: // 取り出して空になった
364: chan->sr0 &= ~SIO::SR0_RXAVAIL;
365: ChangeInterrupt();
366: } else {
1.1.1.6 root 367: chan->rxbuf[0] = chan->rxbuf[1];
368: chan->rxbuf[1] = chan->rxbuf[2];
1.1 root 369: }
370: } else {
371: // XXX 何が読めるか
372: data = 0xff;
1.1.1.5 root 373: putlog(3, "Ch%s Data -> $%02x (Empty)", chan->name, data);
1.1 root 374: }
375:
376: return data;
377: }
378:
379: // データポートの書き込み
380: void
381: uPD7201Device::WriteData(struct SIO::channel *chan, uint32 data)
382: {
383: char charbuf[4];
384:
385: if (isprint((int)data)) {
386: snprintf(charbuf, sizeof(charbuf), "'%c'", data);
387: } else {
388: charbuf[0] = '\0';
389: }
1.1.1.5 root 390: putlog(3, "Ch%s Data <- $%02x %s", chan->name, data, charbuf);
1.1 root 391:
392: // 1文字送信
393:
394: // 今のところ内部バッファがなく常に送信できるので
395: // 必ず Tx Buffer Empty が発生する。
396: chan->sr0 |= SIO::SR0_TXEMPTY;
397:
1.1.1.5 root 398: // 割り込み状態を変える
399: ChangeInterrupt();
1.1 root 400: }
401:
1.1.1.2 root 402: // データポートの Peek
403: uint8
404: uPD7201Device::PeekData(const struct SIO::channel *chan) const
405: {
406: if (chan->rxlen > 0) {
407: // 受信バッファにデータがあれば先頭バイトが見える
408: return chan->rxbuf[0];
409: } else {
410: // 空の時は?
411: return 0xff;
412: }
413: }
414:
1.1.1.3 root 415: // TX/RX の bits/char のレジスタ値を実際の bits/char の値に変換する。
1.1 root 416: /* static */
417: const int
418: uPD7201Device::bits_per_char[] = { 5, 7, 6, 8 };
419:
420: // 1バイト受信する。
421: // 受理されれば true を返す。
422: bool
423: uPD7201Device::Rx(int ch, uint32 data)
424: {
425: struct SIO::channel *chan = &cr.chan[ch];
426:
427: // Rx Enable でなければ受け取らない?
428: if ((chan->cr3 & SIO::CR3_RX_EN) == 0) {
429: return false;
430: }
431:
1.1.1.5 root 432: // 1バイトでもあれば有効
433: chan->sr0 |= SIO::SR0_RXAVAIL;
434:
1.1 root 435: // バッファが一杯なら Rx Overrun Error
436: if (chan->rxlen == sizeof(chan->rxbuf)) {
437: putlog(2, "Rx Overrun");
438: chan->sr1 |= SIO::SR1_RXOVERRUN;
1.1.1.5 root 439: // XXX special Rx condition interrupt occurs
1.1 root 440: return false;
441: }
442:
443: // 受信
444: chan->rxbuf[chan->rxlen++] = data;
445:
1.1.1.5 root 446: // 割り込み状態を変更
447: ChangeInterrupt();
448:
449: return true;
450: }
451:
452: // 割り込み状態を変更
453: void
454: uPD7201Device::ChangeInterrupt()
455: {
456: uint int_asserted = 0;
457:
458: for (int ch = 0; ch < 2; ch++) {
459: struct SIO::channel *chan = &cr.chan[ch];
460:
461: // Rx
462: bool rx_avail = (chan->rxlen > 0) && chan->all_or_first;
463: // Special Rx
464: bool special = false; // XXX not yet
465:
466: bool rx_enable = (chan->cr3 & SIO::CR3_RX_EN);
467: bool rx_int = (rx_enable && (rx_avail || special));
468:
469: // FirstChar モードなら1文字受信割り込み後にフラグを下ろす
470: // (Rx 割り込み用の変数 rx_int が確定したここで行う)
471: if ((chan->cr1 & SIO::CR1_RXINT) == SIO::RXINT_FIRSTCHAR) {
472: chan->all_or_first = false;
1.1 root 473: }
1.1.1.5 root 474:
475: // XXX E/S not yet
476:
477: // Tx
478: bool tx_empty = (chan->sr0 & SIO::SR0_TXEMPTY);
479: bool tx_enable = (chan->cr1 & SIO::CR1_TXINT_EN);
480: // reset_txint_pend は通常 true、コマンド発行で false に落ちる。
481: // XXX INT DMA Mode はよく分からんのでスルー
482: bool tx_int = (tx_empty && tx_enable && chan->reset_txint_pend);
483:
484: // 4つの要因の合成
485: chan->int_asserted = 0;
486: chan->int_asserted |= tx_int ? SIO::INTR_TX : 0;
487: chan->int_asserted |= rx_int ? SIO::INTR_RX : 0;
488:
489: // 両方のチャンネル分を合成
490: int_asserted |= chan->int_asserted;
1.1 root 491: }
492:
1.1.1.5 root 493: gInterrupt->ChangeINT(this, int_asserted);
1.1 root 494: }
495:
496: // モニター
1.1.1.4 root 497: void
1.1.1.7 ! root 498: uPD7201Device::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 499: {
1.1.1.5 root 500: int y;
501:
1.1.1.7 ! root 502: screen.Clear();
1.1 root 503: for (int i = 0; i < 2; i++) {
504: int x = 0;
1.1.1.5 root 505: y = i * 10;
1.1.1.7 ! root 506: MonitorUpdateCh(screen, i, x, y);
1.1 root 507: }
1.1.1.5 root 508:
509: // CR2A
510: uint cr2a = cr.cr2a;
511: y = 20;
1.1.1.7 ! root 512: screen.Print(0, y, "CR2A:$%02x", cr2a);
1.1.1.5 root 513: if ((cr2a & 0x80)) {
1.1.1.7 ! root 514: screen.Print(9, y, TA::On, "SYNC");
1.1.1.5 root 515: } else {
1.1.1.7 ! root 516: screen.Print(9, y, "RTSB");
1.1.1.5 root 517: }
1.1.1.7 ! root 518: screen.Print(14, y, "----");
! 519: screen.Print(19, y, TA::OnOff((cr2a & 0x20)), "Vect");
1.1.1.5 root 520: if ((cr2a & 0x18) == 0x10) {
1.1.1.7 ! root 521: screen.Print(24, y, "IM=V4-V2");
1.1.1.5 root 522: } else {
1.1.1.7 ! root 523: screen.Print(24, y, "IM=V2-V0");
1.1.1.5 root 524: }
525: // bit2 (Priority Select) は bit0 が 0 の時だけ意味があるようだ
526: if ((cr2a & 0x01) == 0) {
527: if ((cr2a & 0x04)) {
1.1.1.7 ! root 528: screen.Print(34, y, "RxTx");
1.1.1.5 root 529: } else {
1.1.1.7 ! root 530: screen.Print(34, y, "A->B");
1.1.1.5 root 531: }
532: }
533: // bit1,0 はよく分からん
1.1.1.7 ! root 534: screen.Print(39, y, "INT/DMA=%d", (cr2a & 0x3));
1.1.1.5 root 535: y++;
536:
537: // CR2B
1.1.1.7 ! root 538: screen.Print(0, y, "CR2B:$%02x", cr.vector);
1.1 root 539: }
540:
541: // モニター (1チャンネル)
542: void
1.1.1.7 ! root 543: uPD7201Device::MonitorUpdateCh(TextScreen& screen,
1.1.1.4 root 544: int ch, int xbase, int ybase)
1.1 root 545: {
546: struct SIO::channel *chan = &cr.chan[ch];
547: uint cr0;
548: uint cr1;
549: uint cr3;
550: uint cr4;
551: uint cr5;
552: uint sr0;
553: uint sr1;
554: uint rxlen;
555: int x;
556: int y;
557:
1.1.1.5 root 558: cr0 = (chan->cr0 & ~SIO::CR0_PTR) | chan->ptr;
1.1 root 559: cr1 = chan->cr1;
560: cr3 = chan->cr3;
561: cr4 = chan->cr4;
562: cr5 = chan->cr5;
563: sr0 = chan->sr0;
564: sr1 = chan->sr1;
565: rxlen = chan->rxlen;
566:
567: // 0 1 2 3 4 5 6
568: // 012345678901234567890123456789012345678901234567890123456789012345
569: // 0123 0123 0123 0123 0123 0123 0123 0123
1.1.1.5 root 570: // CR0: $xx CRC=x CMD=x PTR=x
571: // CR1: $xx WE 0 WR RXInt=x 0 TXEn ESEn
572: // RXBuf: 0 --- --- --- Intr: Rx Sp Tx ES
1.1 root 573:
574: x = xbase;
575: y = ybase;
1.1.1.7 ! root 576: screen.Print(x, y++, "Channel %s: %s", chan->name, chan->desc);
! 577: screen.Print(x, y++, "CR0: $%02x", cr0);
! 578: screen.Print(x, y++, "CR1: $%02x", cr1);
! 579: screen.Print(x, y++, "CR3: $%02x", cr3);
! 580: screen.Print(x, y++, "CR4: $%02x", cr4);
! 581: screen.Print(x, y++, "CR5: $%02x", cr5);
! 582: screen.Print(x, y++, "SR0: $%02x", sr0);
! 583: screen.Print(x, y++, "SR1: $%02x", sr1);
! 584: screen.Print(x, y, "RXbuf: %d", rxlen);
1.1 root 585: int i;
586: for (i = 0; i < rxlen; i++) {
1.1.1.7 ! root 587: screen.Print(x + 9 + i * 4, y, "$%02x", chan->rxbuf[i]);
1.1 root 588: }
589: for (; i < sizeof(chan->rxbuf); i++) {
1.1.1.7 ! root 590: screen.Print(x + 9 + i * 4, y, "---");
1.1 root 591: }
1.1.1.5 root 592: // 内部割り込み状態
1.1.1.7 ! root 593: screen.Print(31, y, "Intr:");
! 594: screen.Print(37, y, TA::OnOff(chan->int_asserted & SIO::INTR_RX), "Rx");
! 595: screen.Print(40, y, TA::OnOff(chan->int_asserted & SIO::INTR_SP), "SP");
! 596: screen.Print(43, y, TA::OnOff(chan->int_asserted & SIO::INTR_TX), "Tx");
! 597: screen.Print(46, y, TA::OnOff(chan->int_asserted & SIO::INTR_ES), "ES");
1.1 root 598:
599: y = ybase + 1;
600: x = xbase;
601: // CR0
1.1.1.7 ! root 602: screen.Print(x + 9, y, "CRC=%d", (cr0 >> 6));
1.1 root 603: static const char * const cmd_str[] = {
604: // 0123456789012345
605: "No operation",
606: "Send Abort",
607: "Reset E/S Int",
608: "Channel Reset",
609: "Enable IntNextCh",
610: "Reset TxIntPend",
611: "Error Reset",
612: "End of Interrupt",
613: };
614: uint cmd = (cr0 >> 3) & 7;
1.1.1.7 ! root 615: screen.Print(x + 19, y, "CMD=%d(%s)", cmd, cmd_str[cmd]);
! 616: screen.Print(x + 43, y, "PTR=%d", (cr0 & 7));
1.1 root 617: y++;
618:
619: // CR1
620: static const char * const cr1_str[] = {
621: "WaEn", "----", "WaRx", "", "", "----", "TxIE", "ESEn"
622: };
1.1.1.7 ! root 623: MonitorReg(screen, x + 9, y, cr1, cr1_str);
1.1.1.5 root 624: static const char * const rxint_str[] = {
625: // 2345678
626: "=SpOnly",
627: "=AllChr",
628: "=1stChr",
629: "Disable",
630: };
1.1.1.7 ! root 631: screen.Print(x + 24, y, "RI%s", rxint_str[(cr1 >> 3) & 3]);
1.1 root 632: y++;
633:
634: // CR3
635: static const char * const cr3_str[] = {
636: "", "", "AuEn", "----", "----", "----", "----", "RXEn"
637: };
1.1.1.7 ! root 638: MonitorReg(screen, x + 9, y, cr3, cr3_str);
! 639: screen.Print(x + 9, y, "RXbits=%d", 5 + ((cr3 >> 6) & 3));
1.1 root 640: y++;
641:
642: // CR4
643: static const char * const cr4_str[] = {
644: "", "", "", "", "", "", "PaEv", "PaEn"
645: };
1.1.1.7 ! root 646: MonitorReg(screen, x + 9, y, cr4, cr4_str);
1.1 root 647:
648: static const char * const clkrate_str[] = {
649: "1", "16", "32", "64"
650: };
1.1.1.7 ! root 651: screen.Print(x + 9, y, "Rate=x%s", clkrate_str[(cr4 >> 6) & 3]);
1.1 root 652: static const char * const syncmode_str[] = {
653: "Mono", "Bi", "HDLC", "Ext"
654: };
1.1.1.7 ! root 655: screen.Print(x + 19, y, "Sync=%s", syncmode_str[(cr4 >> 4) & 3]);
1.1 root 656: static const char * const stopbit_str[] = {
657: "Sync", "1", "1.5", "2"
658: };
1.1.1.7 ! root 659: screen.Print(x + 29, y, "Stop=%s", stopbit_str[(cr4 >> 2) & 3]);
1.1 root 660: y++;
661:
662: // CR5
663: static const char * const cr5_str[] = {
664: "DTR", "", "", "SBrk", "TXEn", "CRC", "!RTS", "TCEn"
665: };
1.1.1.7 ! root 666: MonitorReg(screen, x + 9, y, cr5, cr5_str);
! 667: screen.Print(x + 14, y, "TXbits=%d", 5 + ((cr5 >> 5) & 3));
1.1 root 668: y++;
669:
670: // SR0
671: static const char * const sr0_str[] = {
672: "BrAb", "TxUn", "CTS", "SYNC", "DCD", "TxEm", "IntP", "RxAv"
673: };
1.1.1.7 ! root 674: MonitorReg(screen, x + 9, y, sr0, sr0_str);
1.1.1.5 root 675: // SR0 の bit1 (Interrupt Pending) は SR0A のみ。SR0B では 0。
676: if (ch == 1) {
1.1.1.7 ! root 677: screen.Print(39, y, "----");
1.1.1.5 root 678: }
1.1 root 679: y++;
680:
681: // SR1
682: static const char * const sr1_str[] = {
683: "EOF", "CRCE", "RxOv", "PaEr", "", "", "", "Sent"
684: };
1.1.1.7 ! root 685: MonitorReg(screen, x + 9, y, sr1, sr1_str);
! 686: screen.Print(x + 29, y, "ResidueCode=%d", (sr1 >> 1) & 7);
1.1 root 687: y++;
688: }
689:
690: // レジスタをビットごとに表示する。MonitorUpdate の下請け。
691: void
1.1.1.7 ! root 692: uPD7201Device::MonitorReg(TextScreen& screen,
1.1.1.4 root 693: int x, int y, uint32 reg, const char * const *names)
1.1 root 694: {
695: for (int i = 0; i < 8; i++) {
696: if (strcmp(names[i], "----") == 0) {
1.1.1.7 ! root 697: screen.Puts(x + i * 5, y, TA::Disable, names[i]);
1.1 root 698: } else {
699: bool b = reg & (1 << (7 - i));
1.1.1.7 ! root 700: screen.Puts(x + i * 5, y, TA::OnOff(b), names[i]);
1.1 root 701: }
702: }
703: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.