Annotation of nono/vm/upd7201.cpp, revision 1.1.1.7

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.