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