Annotation of nono/vm/mpscc.h, revision 1.1.1.9

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // uPD7201(MPSC) と Z8530(SCC) の共通部分 (シリアルポート1個つき)
                      9: //
                     10: 
                     11: #pragma once
                     12: 
                     13: #include "device.h"
                     14: #include "message.h"
                     15: #include <array>
                     16: 
                     17: #if defined(MPSCC_SIO_LOG_HACK)
                     18: // SIO で SR0 のログ表示に細工をするため、
                     19: // SIO, MPSCC で putlog() マクロを再定義している。
                     20: #undef putlog
                     21: #define putlog(lv, fmt...)     do {    \
                     22:        if (__predict_false(loglevel >= (lv))) {        \
                     23:                putlogn(fmt);   \
                     24:                sr0_logphase = 0;       \
                     25:        }       \
                     26: } while (0)
                     27: #endif
                     28: 
                     29: class HostCOMDevice;
1.1.1.3   root       30: class InterruptDevice;
1.1       root       31: 
                     32: // 1チャンネル分の共通部分
1.1.1.8   root       33: class MPSCCChan final
1.1       root       34: {
                     35:  public:
                     36:        MPSCCChan();
1.1.1.8   root       37:        ~MPSCCChan();
1.1       root       38: 
                     39:        void Init(int id_);
                     40: 
                     41:        // プロパティっぽいもの
                     42:        int id {};                              // チャンネル番号 (0 or 1)
                     43:        char name {};                   // チャンネル名 ('A' or 'B')
                     44:        const char *desc {};    // チャンネルの用途(モニタ表示用)
                     45:        uint32 ctrladdr {};             // 制御ポートのアドレス (モニタ表示用)
                     46:        uint32 dataaddr {};             // データポートのアドレス (モニタ表示用)
                     47: 
                     48:        // ここから内部構造
                     49: 
                     50:        // CR0/WR0 付近
                     51:        uint8 crc_cmd {};               // CRC
                     52:        uint8 cmd {};                   // Command
                     53:        uint ptr {};                    // Pointer (uPD7201 は 3bit、Z8530 は実質 4bit)
                     54: 
                     55:        // CR1/WR1 付近
                     56:        bool wait_enable {};    // b7
                     57:        bool wait_func {};              // b6; Z8530 Only
                     58:        bool wait_on_rx {};             // b5
                     59:        bool txint_enable {};   // b1
                     60:        bool esint_enable {};   // b0
                     61: 
                     62:        // Z8530 では割り込みモード3種類とパリティエラーを Sp.Rx に含むかどうかが
                     63:        // 独立して選択できるため、組み合わせは 3 * 2 (+ Disable 1通り) = 7通り。
                     64:        // uPD7201 ではこれに相当する設定は RXINT の 2bit しかなく、Disable を除く
                     65:        // 3通りはこのうち 3つがプリセットされたような感じ。
                     66:        // (もちろん歴史的経緯はこの逆だろうけど)
                     67:        //
                     68:        //         RXInt SP    割込モード  Parity Error を Sp.Rx に含むか
                     69:        // -----------------   ------------     ------------------------------
                     70:        //          0  0  -  : Disable          -
                     71:        // uPD7201  0  1  -  : 1stChar          no
                     72:        // uPD7201  1  0  -  : AllChar          yes
                     73:        // uPD7201  1  1  -  : AllChar          no
                     74:        // Z8530    0  1  0  : 1stChar          no
                     75:        // Z8530    0  1  1  : 1stChar          yes
                     76:        // Z8530    1  0  0  : AllChar          no
                     77:        // Z8530    1  0  1  : AllChar          yes
                     78:        // Z8530    1  1  0  : SpOnly           no
                     79:        // Z8530    1  1  1  : SpOnly           yes
                     80:        static const uint RXINT_DISABLE = 0x00;
                     81:        static const uint RXINT_1STCHAR = 0x01;
                     82:        static const uint RXINT_ALLCHAR = 0x02;
                     83:        static const uint RXINT_SPONLY  = 0x03; // Z8530 Only
                     84:        uint rxint_mode {};
                     85:        bool sp_parity {};
                     86: 
                     87:        // SR0/RR0 付近
                     88:        bool break_detected {};
                     89:        bool tx_underrun {};
                     90:        bool nCTS {};
                     91:        bool nSYNC {};
                     92:        bool nDCD {};
                     93: 
                     94:        // これらのレジスタは uPD7201/Z8530 で共通
                     95: 
1.1.1.2   root       96:        // CR3/WR3 付近
1.1.1.5   root       97:        uint rxbits {};                 // 受信データビット数 (レジスタ値ではない)
1.1.1.2   root       98:        uint8 cr3_sync {};              // SyncMode でだけ使う bit4-1 を保存
                     99:        bool auto_enable {};
1.1       root      100:        bool rx_enable {};
1.1.1.2   root      101: 
                    102:        // CR4/WR4 付近
1.1.1.5   root      103:        uint clkrate {};                // クロック倍率 (レジスタ値ではない)
1.1.1.2   root      104:        uint8 syncmode {};              // bit5,4 を保存
                    105:        uint8 stopbits {};              // STOPBITS_*
                    106:        bool parity_even {};
                    107:        int parity_enable {};   // パリティ有効 (追加するビット数 0 か 1 で保持)
                    108: 
                    109:        // CR5/WR5 付近
                    110:        bool nDTR {};                   // ~DTR
1.1.1.5   root      111:        uint txbits {};                 // 送信データビット数 (レジスタ値ではない)
1.1.1.2   root      112:        bool sendbreak {};
1.1       root      113:        bool tx_enable {};
1.1.1.2   root      114:        bool crc16 {};
                    115:        bool nRTS {};                   // ~RTS
                    116:        bool txcrc_en {};
                    117: 
1.1       root      118:        uint8 cr6 {};
                    119:        uint8 cr7 {};
                    120:        uint8 sr1 {};
                    121: 
1.1.1.2   root      122:        // いずれもレジスタイメージとして保存
                    123:        uint8 old_cr3 {};
                    124:        uint8 old_cr4 {};
                    125:        uint8 old_cr5 {};
                    126: 
1.1       root      127:        // Z8530 専用のレジスタだけど継承とかは面倒なので結局ここに置く
                    128:        uint8 wr10 {};
                    129:        uint8 wr11 {};
                    130:        uint16 tc {};                   // WR12, WR13
                    131:        uint8 wr14 {};
                    132:        uint8 wr15 {};
                    133:        uint8 rr10 {};
                    134: 
                    135:        // ここからその他の内部状態
                    136: 
                    137:        bool es_latched {};             // E/S ビットがラッチされているか
                    138: 
                    139:        // 受信バッファは短いので先頭からの FIFO とし、
                    140:        // 取り出したら前にずらす
                    141:        uint8 rxbuf[3] {};              // 受信バッファ(FIFO)
                    142:        int   rxlen {};                 // 受信バッファの有効バイト数
                    143: 
                    144:        uint8 txbuf {};                 // 送信バッファ
                    145:        int   txlen {};                 // 送信バッファの有効バイト数
                    146:        uint8 tx_shiftreg {};   // 送信シフトレジスタ相当品
                    147: 
                    148:        // First Char 用のフラグで、この受信で割り込みを起こすなら true。
                    149:        // ALL なら常に true。FIRSTCHAR の時は最初が true で1文字目の受信
                    150:        // 割り込みを出したところで false にする。
                    151:        bool all_or_first {};
                    152: 
                    153:        // Tx 割り込み発火用のフラグ。
                    154:        // Tx 割り込みは
                    155:        // 1) Tx 割り込みが有効で
                    156:        // 2) 送信バッファに書き込まれるか Reset Tx INT/DMA Pending コマンドが
                    157:        //    発行されるかした後
                    158:        // 3) 送信バッファが空になった
                    159:        // 場合に発生する。チャンネルリセットとハードリセットで送信バッファが
                    160:        // 空になった場合には発生しない。
                    161:        // ので、ここの 2) を満たす場合 txint_ready = true とする。
                    162:        bool txint_ready {};
                    163: 
                    164:        // 割り込みペンディング (MPSCC::INTPEND_*)
                    165:        //
                    166:        // Z8530 の RR3A レジスタは個別の割り込みペンディング状態が読み出せる。
                    167:        // uPD7201 にも内部に同じだけの状態を持っているが個別に読み出す方法はなく
                    168:        // すべてを OR したペンディングの有無を SR0A b1 で読み出すことが出来る。
                    169:        uint intpend {};
                    170: 
                    171:        // ボーレート (表示用)
                    172:        // Z8530 なら tc から求められる
                    173:        double baudrate {};
                    174: 
                    175:        // 1フレームあたりの送受信のビット数 (表示用)
1.1.1.5   root      176:        uint txframebits {};
                    177:        uint rxframebits {};
1.1.1.2   root      178: 
                    179:        // LUNA の場合は TxC, RxC ピンに供給されているクロック。
                    180:        // X68030 の場合は Z8530 内部で生成されている基準クロック。
1.1.1.9 ! root      181:        // 誤差を減らすため 12 ビット分の時間 [tsec] としている。
        !           182:        uint64 xc12_tsec {};
1.1.1.2   root      183: 
1.1.1.9 ! root      184:        // 実際の 12 ビットの通信にかかる時間。xc12_tsec に倍率をかけたもの。
        !           185:        uint64 bit12_tsec {};
1.1       root      186: };
                    187: 
                    188: class MPSCC
                    189: {
                    190:  public:
                    191:        // レジスタ定義
                    192: 
                    193:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    194:        //      +---------+--------------+--------------+
                    195:        // CR0  |   CRC   |   Command    |   Pointer    |
                    196:        // WR0  +---------+--------------+--------------+
                    197:        //
                    198:        static const uint8 CR0_CRC                      = 0xc0;
                    199:        static const uint8 CR0_CMD                      = 0x38;
                    200:        static const uint8 CR0_PTR                      = 0x07;
                    201:        // Z8530 ではコマンド %000 と %001 がレジスタ切り替えなので、
                    202:        // CMD が 0x38、PTR が 0x0f とあえて被せてある。
                    203:        static const uint8 WR0_CRC                      = CR0_CRC;
                    204:        static const uint8 WR0_CMD                      = CR0_CMD;
                    205:        static const uint8 WR0_PTR                      = 0x0f;
                    206: 
                    207:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    208:        //      +----+----+----+---------+----+----+----+
                    209:        // CR1  | WE |  0 | WR |  RX Int | SAV| TE | ES |
                    210:        //      +----+----+----+---------+----+----+----+
                    211:        //        |         |       |      |    |    +---- E/S Int Enable
                    212:        //        |         |       |      |    +--------- TX INT/DMA Enable
                    213:        //        |         |       |      +-------------- Status Affects Vec.(Ch.B)
                    214:        //        |         |       +--------------------- RX Int Mode
                    215:        //        |         +----------------------------- Wait on RX(=%1),TX(=%0)
                    216:        //        +--------------------------------------- Wait Enable
                    217:        //
                    218:        static const uint8 CR1_WAIT_EN          = 0x80; // Wait Enable
                    219:        static const uint8 CR1_WAIT_RX          = 0x20; // Wait on RX
                    220:        static const uint8 CR1_RXINT            = 0x18; // Rx Interrupt Mode
                    221:        static const uint8 CR1_RXINT_DISABLE    = 0x00; // Disable
                    222:        static const uint8 CR1_RXINT_1STCHAR    = 0x08; // 1st Char
                    223:        static const uint8 CR1_RXINT_ALLCHAR    = 0x10; // All Chars
                    224:        static const uint8 CR1_RXINT_ALL_BUT_PE = 0x18; // All Chars exclude P.E.
                    225:        static const uint8 CR1_SAV                      = 0x04; // Status Affects Vector (Ch.B)
                    226:        static const uint8 CR1_TXINT_EN         = 0x02; // Tx Int/DMA Enable
                    227:        static const uint8 CR1_ESINT_EN         = 0x01; // E/S Interrupt Enable
                    228:        //
                    229:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    230:        //      +----+----+----+---------+----+----+----+
                    231:        // WR1  | WE | WF | WR |  RX Int | SP | TE | ES |
                    232:        //      +----+----+----+---------+----+----+----+
                    233:        //             |                   +-------------- Sp includes Parity Err
                    234:        //             +---------------------------------- Wait Function
                    235:        //
                    236:        static const uint8 WR1_WAIT_EN          = CR1_WAIT_EN;
                    237:        static const uint8 WR1_WAIT_FUNC        = 0x40; // Wait Function
                    238:        static const uint8 WR1_WAIT_RX          = CR1_WAIT_RX;
                    239:        static const uint8 WR1_RXINT            = CR1_RXINT;
                    240:        static const uint8 WR1_RXINT_DISABLE    = 0x00; // Disable
                    241:        static const uint8 WR1_RXINT_1STCHAR    = 0x08; // 1st Char or Sp.Cond.
                    242:        static const uint8 WR1_RXINT_ALLCHAR    = 0x10; // All Chars or Sp.Cond.
                    243:        static const uint8 WR1_RXINT_SPONLY             = 0x18; // Special Conditoin Only
                    244:        static const uint8 WR1_SP_INC_PE        = 0x04; // Sp. Condition includes P.E.
                    245:        static const uint8 WR1_TXINT_EN         = CR1_TXINT_EN;
                    246:        static const uint8 WR1_ESINT_EN         = CR1_ESINT_EN;
                    247: 
                    248:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    249:        //      +----+----+----+---------+----+---------+
                    250:        // CR2A | R/S|  0 | VM | IntMode | PS | Int/DMA |
                    251:        //      +----+----+----+---------+----+---------+
                    252:        //        |         |       |      |       +------ INT/DMA Mode
                    253:        //        |         |       |      +-------------- Priority Select
                    254:        //        |         |       +--------------------- Interrupt Mode -> VIS
                    255:        //        |         +----------------------------- Vector Mode
                    256:        //        +--------------------------------------- ~RTSB/~SYNCB Select
                    257:        //
                    258:        static const uint8 CR2_SYNCB            = 0x80; // ~RTSB/~SYNCB Select
                    259:        static const uint8 CR2_VM                       = 0x20; // Vector Mode
                    260:        static const uint8 CR2_INT                      = 0x18; // Interrupt Mode -> VIS
                    261:        static const uint8 CR2_PRIOSEL          = 0x04; // Priority Select
                    262:        static const uint8 CR2_INTDMA           = 0x03; // Int/DMA Mode
                    263: 
                    264:        //       b7   b6   b5   b4   b3   b2   b1   b0
                    265:        //     +---------+----+-------------------+----+
                    266:        // CR3 | RX bits | AE |  (For sync mode)  | RE |
                    267:        // WR3 +---------+----+-------------------+----+
                    268:        //          |      |                        +---- RX Enable
                    269:        //          |      +----------------------------- Auto Enable
                    270:        //          +------------------------------------ RX bits
                    271:        //
                    272:        static const uint8 CR3_RXBITS           = 0xc0; // Rx Bits
                    273:        static const uint8 CR3_AUTO_EN          = 0x40; // Auto Enable
1.1.1.2   root      274:        static const uint8 CR3_SYNC_MASK        = 0x1e;
1.1       root      275:        static const uint8 CR3_RX_EN            = 0x01; // Rx Enable
                    276:        // WR3
                    277:        static const uint8 WR3_RXBITS           = CR3_RXBITS;
                    278:        static const uint8 WR3_AUTO_EN          = CR3_AUTO_EN;
                    279:        static const uint8 WR3_RX_EN            = CR3_RX_EN;
                    280: 
                    281:        // 並び順が 5, 6, 7, 8 でないので注意
                    282:        static const uint8 RXBITS_5                     = 0x00;
                    283:        static const uint8 RXBITS_7                     = 0x40;
                    284:        static const uint8 RXBITS_6                     = 0x80;
                    285:        static const uint8 RXBITS_8                     = 0xc0;
                    286: 
                    287:        //       b7   b6   b5   b4   b3   b2   b1   b0
                    288:        //     +---------+---------+---------+----+----+
                    289:        // CR4 | ClkRate | SyncMode| StopBits| PEV| PEN|
                    290:        // WR4 +---------+---------+---------+----+----+
                    291:        //          |         |         |      |    +---- Parity Enable(%1)
                    292:        //          |         |         |      +--------- Parity Even(%1)
                    293:        //          |         |         +---------------- Stop Bits
                    294:        //          |         +-------------------------- Sync Mode
                    295:        //          +------------------------------------ Clock Rate
                    296:        //
                    297:        static const uint8 CR4_CLKRATE          = 0xc0; // Clock Rate
                    298:        static const uint8 CR4_SYNCMODE         = 0x30; // Sync Mode
                    299:        static const uint8 CR4_STOPBITS         = 0x0c; // Stop Bits
                    300:        static const uint8 CR4_PARITY_EVEN      = 0x02; // Parity Even
                    301:        static const uint8 CR4_PARITY_EN        = 0x01; // Parity Enable
                    302:        // WR4
                    303:        static const uint8 WR4_CLKRATE          = CR4_CLKRATE;
                    304:        static const uint8 WR4_SYNCMODE         = CR4_SYNCMODE;
                    305:        static const uint8 WR4_STOPBITS         = CR4_STOPBITS;
                    306:        static const uint8 WR4_PARITY_EVEN      = CR4_PARITY_EVEN;
                    307:        static const uint8 WR4_PARITY_EN        = CR4_PARITY_EN;
                    308: 
1.1.1.2   root      309:        static const uint8 CLKRATE_1            = 0x00;
                    310:        static const uint8 CLKRATE_16           = 0x40;
                    311:        static const uint8 CLKRATE_32           = 0x80;
                    312:        static const uint8 CLKRATE_64           = 0xc0;
                    313: 
                    314:        static const uint8 STOPBITS_SYNC        = (0x00 >> 2);
                    315:        static const uint8 STOPBITS_1           = (0x04 >> 2);
                    316:        static const uint8 STOPBITS_1_5         = (0x08 >> 2);
                    317:        static const uint8 STOPBITS_2           = (0x0c >> 2);
1.1       root      318: 
                    319:        //       b7   b6   b5   b4   b3   b2   b1   b0
                    320:        //     +----+---------+----+----+----+----+----+
                    321:        // CR5 |~DTR| TX bits | SB | TE | CRC|~RTS| TCE|
                    322:        // WR5 +----+---------+----+----+----+----+----+
                    323:        //               |      |    |    |         +---- TX CRC Enable
                    324:        //               |      |    |    +-------------- CRC-16/CCITT
                    325:        //               |      |    +------------------- TX Enable
                    326:        //               |      +------------------------ Send Break
                    327:        //               +------------------------------- TX Bits
                    328:        static const uint8 CR5_nDTR                     = 0x80; // ~DTR
                    329:        static const uint8 CR5_TXBITS           = 0x60; // Tx Bits
                    330:        static const uint8 CR5_SENDBREAK        = 0x10; // Send Break
                    331:        static const uint8 CR5_TX_EN            = 0x08; // Tx Enable
                    332:        static const uint8 CR5_CRC16            = 0x04; // CRC-16/CCITT
                    333:        static const uint8 CR5_nRTS                     = 0x02; // ~RTS
                    334:        static const uint8 CR5_TXCRC_EN         = 0x01; // Tx CRC Enable
                    335:        // WR5
                    336:        static const uint8 WR5_nDTR                     = CR5_nDTR;
                    337:        static const uint8 WR5_TXBITS           = CR5_TXBITS;
                    338:        static const uint8 WR5_SENDBREAK        = CR5_SENDBREAK;
                    339:        static const uint8 WR5_TX_EN            = CR5_TX_EN;
                    340:        static const uint8 WR5_CRC16            = CR5_CRC16;
                    341:        static const uint8 WR5_nRTS                     = CR5_nRTS;
                    342:        static const uint8 WR5_TXCRC_EN         = CR5_TXCRC_EN;
                    343: 
                    344:        // 並び順が 5, 6, 7, 8 でないので注意
                    345:        static const uint8 TXBITS_5                     = 0x00;
                    346:        static const uint8 TXBITS_7                     = 0x20;
                    347:        static const uint8 TXBITS_6                     = 0x40;
                    348:        static const uint8 TXBITS_8                     = 0x60;
                    349: 
                    350:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    351:        //      +---------+----+----+----+----+----+----+
                    352:        // WR9A |  Reset  |  0 |SHSL| MIE| DLC| NV | VIS|
                    353:        // WR9B +---------+----+----+----+----+----+----+
                    354:        //           |           |    |    |    |    +---- Vector Includes Status
                    355:        //           |           |    |    |    +--------- No Vector Mode
                    356:        //           |           |    |    +-------------- Disable Lower Chain
                    357:        //           |           |    +------------------- Master Interrupt Enable
                    358:        //           |           +------------------------ StatusHigh / StatusLow
                    359:        //           +------------------------------------ Reset Command
                    360:        // Reset Command は CR0 のコマンドも参照のこと。
                    361:        //
                    362:        static const uint8 WR9_RESET_CMD        = 0xc0; // Reset Command
                    363:        static const uint8 WR9_SHSL                     = 0x10; // Status High / Status Low
                    364:        static const uint8 WR9_MIE                      = 0x08; // Master Interrupt Enable
                    365:        static const uint8 WR9_DLC                      = 0x04; // Disable Lower Chain
                    366:        static const uint8 WR9_NV                       = 0x02; // No Vector Mode
                    367:        static const uint8 WR9_VIS                      = 0x01; // Vector Includes Status
                    368: 
                    369:        //       b7   b6   b5   b4   b3   b2   b1   b0
                    370:        //     +----+----+----+----+----+----+----+----+
                    371:        // SR0 | B/A| T/E|~CTS|~S/H|~DCD| TE | IP | RA |
                    372:        //     +----+----+----+----+----+----+----+----+
                    373:        //       |    |         |         |    |    +---- Rx Char. Available
                    374:        //       |    |         |         |    +--------- Interrupt Pending
                    375:        //       |    |         |         +-------------- Tx Buffer Empty
                    376:        //       |    |         +------------------------ ~SYNC/Hunt
                    377:        //       |    +---------------------------------- Tx Underrun/EOM
                    378:        //       +--------------------------------------- Break/Abort
                    379:        //
                    380:        static const uint8 SR0_BREAK            = 0x80; // Break/Abort
                    381:        static const uint8 SR0_TXUNDER          = 0x40; // Tx Underrun/EOM
                    382:        static const uint8 SR0_nCTS                     = 0x20; // ~CTS
                    383:        static const uint8 SR0_nSYNC            = 0x10; // ~SYNC/Hunt
                    384:        static const uint8 SR0_nDCD                     = 0x08; // ~DCD
                    385:        static const uint8 SR0_TXEMPTY          = 0x04; // Tx Buffer Empty
                    386:        static const uint8 SR0_INTPEND          = 0x02; // Interrupt Pending
                    387:        static const uint8 SR0_RXAVAIL          = 0x01; // Rx Character Available
                    388:        //
                    389:        //     +----+----+----+----+----+----+----+----+
                    390:        // RR0 | B/A| T/E|~CTS|~S/H|~DCD| TE | ZC | RA |
                    391:        //     +----+----+----+----+----+----+----+----+
                    392:        //                                     +--------- Zero Count
                    393:        //
                    394:        static const uint8 RR0_BREAK            = SR0_BREAK;
                    395:        static const uint8 RR0_TXUNDER          = SR0_TXUNDER;
                    396:        static const uint8 RR0_nCTS                     = SR0_nCTS;
                    397:        static const uint8 RR0_nSYNC            = SR0_nSYNC;
                    398:        static const uint8 RR0_nDCD                     = SR0_nDCD;
                    399:        static const uint8 RR0_TXEMPTY          = SR0_TXEMPTY;
                    400:        static const uint8 RR0_ZEROCNT          = 0x02; // Zero Count
                    401:        static const uint8 RR0_RXAVAIL          = SR0_RXAVAIL;
                    402: 
                    403:        //       b7   b6   b5   b4   b3   b2   b1   b0
                    404:        //     +----+----+----+----+--------------+----+
                    405:        // SR1 | EF | FRE| RO | PE | ResidueCode  | AS |
                    406:        // RR1 +----+----+----+----+--------------+----+
                    407:        //
                    408:        static const uint8 SR1_ENDOFFRAME       = 0x80; // End of Frame
                    409:        static const uint8 SR1_FRAMEERROR       = 0x40; // Framing/CRC Error
                    410:        static const uint8 SR1_RXOVERRUN        = 0x20; // Rx Overrun
                    411:        static const uint8 SR1_PARITYERROR      = 0x10; // Parity Error
                    412:        static const uint8 SR1_RESIDUEMASK      = 0x0e; // Residue Code 2-0
                    413:        static const uint8 SR1_ALL_SENT         = 0x01; // All Sent
                    414:        // RR1
                    415:        static const uint8 RR1_ENDOFFRAME       = SR1_ENDOFFRAME;
                    416:        static const uint8 RR1_FRAMEERROR       = SR1_FRAMEERROR;
                    417:        static const uint8 RR1_RXOVERRUN        = SR1_RXOVERRUN;
                    418:        static const uint8 RR1_PARITYERROR      = SR1_PARITYERROR;
                    419:        static const uint8 RR1_RESIDUEMASK      = SR1_RESIDUEMASK;
                    420:        static const uint8 RR1_ALL_SENT         = SR1_ALL_SENT;
                    421: 
                    422:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    423:        //      +---------+----+----+----+----+----+----+
                    424:        // RR3A |    0    | RxA| TxA| ESA| RxB| TxB| ESB|
                    425:        //      +---------+----+----+----+----+----+----+
                    426:        static const uint8 RR3_RXA                      = 0x20; // Channel A Rx  Int. Pending
                    427:        static const uint8 RR3_TXA                      = 0x10; // Channel A Tx  Int. Pending
                    428:        static const uint8 RR3_ESA                      = 0x08; // Channel A E/S Int. Pending
                    429:        static const uint8 RR3_RXB                      = 0x04; // Channel B Rx  Int. Pending
                    430:        static const uint8 RR3_TXB                      = 0x02; // Channel B Tx  Int. Pending
                    431:        static const uint8 RR3_ESB                      = 0x01; // Channel B E/S Int. Pending
                    432: 
                    433:  public:
                    434:        // 2チャンネル分
                    435:        std::array<MPSCCChan, 2> chan {};
                    436: 
                    437:        // CR2 付近
                    438:        uint8 intdma_mode {};
                    439:        static const uint8 INTDMA_INT_INT = 0;  // Both channel INT
                    440:        static const uint8 INTDMA_DMA_INT = 1;  // ChA DMA, ChB INT
                    441:        static const uint8 INTDMA_DMA_DMA = 2;  // Both channel DMA
                    442:        bool priority_select {};
                    443:        uint8 int_mode {};
                    444:        static const uint8 INTMODE_85_1 = 0;
                    445:        static const uint8 INTMODE_85_2 = 1;
                    446:        static const uint8 INTMODE_86   = 2;
                    447:        // 割り込み時にベクタを出力するなら true。
                    448:        // CR2A の VM は出力なら %1、WR9 の NV(Non Vector) は出力しない時 %1。
                    449:        bool vectored_mode {};
                    450:        bool syncb {};
                    451: 
                    452:        // WR9 付近
                    453:        uint8 wr9_cmd {};                       // WR9 の b6,7
                    454:        bool sav_vis {};                        // uPD7201 なら CR1 SAV、Z8530 なら WR9 VIS
                    455:        bool disable_lower_chain {};
                    456:        bool master_int_enable {};
                    457:        bool status_high_low {};
                    458: 
                    459:        // ベクタに割り込み要因(3bit) を入れるかどうかは、
                    460:        // CR1 なら Status Affects Vector、
                    461:        // WR9 なら Vector Includes Status が担当。
                    462:        // どこに (どの順で) 入れるかは CR2A INT Mode か WR9 bit4 で指定する。
                    463:        enum {
                    464:                VIS_FIXED = 0,
                    465:                VIS_432,        // uPD7201: SAV = %1 && CR2A INT Mode = %00 or %01
                    466:                VIS_210,        // uPD7201: SAV = %1 && CR2A INT Mode = %10
                    467:                VIS_321,        // Z8530:   VIS = %1 && WR9 SHSL = %0
                    468:                VIS_456,        // Z8530:   VIS = %1 && WR9 SHSL = %1 (456; 向きに注意)
                    469:        } vis {};
                    470: 
                    471:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    472:        //      +---------------------------------------+
                    473:        // CR2B |               Vector                  |
                    474:        // WR2  +---------------------------------------+
                    475:        //
                    476:        //        b7   b6   b5   b4   b3   b2   b1   b0
                    477:        //      +---------------------------------------+
                    478:        // RR2A |        Vector (WR2 に書いた値)        |
                    479:        //      +---------------------------------------+
                    480:        //
                    481:        //      +---------------------------------------+
                    482:        // SR2B |   Vector (割り込み要因で変化した値)   |
                    483:        // RR2B +---------------------------------------+
                    484:        uint vector {};
                    485: 
                    486:        // 割り込み要因
                    487:        static const uint VS_TxB        = 0;
                    488:        static const uint VS_ESB        = 1;
                    489:        static const uint VS_RxB        = 2;
                    490:        static const uint VS_SPB        = 3;
                    491:        static const uint VS_TxA        = 4;
                    492:        static const uint VS_ESA        = 5;
                    493:        static const uint VS_RxA        = 6;
                    494:        static const uint VS_SPA        = 7;
                    495:        static const uint VS_none       = 8;    // 割り込みなし
                    496: };
                    497: 
                    498: class MPSCCDevice : public IODevice
                    499: {
                    500:        using inherited = IODevice;
                    501:  protected:
                    502:        // 割り込みペンディングビット。chan.intpend で使用する。
                    503:        static const uint INTPEND_TX            = 0x01;
                    504:        static const uint INTPEND_ES            = 0x02;
                    505:        static const uint INTPEND_RX            = 0x04;
                    506:        static const uint INTPEND_SP            = 0x08;
                    507: 
                    508:        // 今のところ SIO, SCC どちらもシリアルポートはチャンネル 0
                    509:        static const int COM_CH = 0;
                    510: 
                    511:  public:
1.1.1.3   root      512:        MPSCCDevice();
1.1       root      513:        ~MPSCCDevice() override;
                    514: 
                    515:        bool Create() override;
                    516:        void SetLogLevel(int loglevel_) override;
                    517:        bool Init() override;
                    518: 
                    519:        // 1バイト受信 (送信側デバイスが呼ぶ)
                    520:        virtual bool Rx(int ch, uint32 data);
                    521: 
                    522:  protected:
                    523:        // 指定のレジスタ名を返す
1.1.1.5   root      524:        virtual const char *CRName(const MPSCCChan&, uint n) const = 0;
                    525:        virtual const char *SRName(const MPSCCChan&, uint n) const = 0;
1.1       root      526:        // 現在のレジスタ名を返す
                    527:        const char *CRName(const MPSCCChan& chan) const {
                    528:                return CRName(chan, chan.ptr);
                    529:        }
                    530:        const char *SRName(const MPSCCChan& chan) const {
                    531:                return SRName(chan, chan.ptr);
                    532:        }
                    533: 
                    534:        // チャンネルリセットの共通部
                    535:        void ResetChannelCommon(MPSCCChan&);
                    536: 
1.1.1.5   root      537:        // BusIO インタフェース
                    538:        static const uint32 NPORT = 4;
                    539:        bool PokePort(uint32 offset, uint32 data);
                    540: 
1.1       root      541:        // レジスタアクセス
1.1.1.2   root      542:        static uint8 GetCR0(const MPSCCChan&);
                    543:        static void SetCR3(MPSCCChan&, uint32 data);
                    544:        static uint8 GetCR3(const MPSCCChan&);
                    545:        static void SetCR4(MPSCCChan&, uint32 data);
                    546:        static uint8 GetCR4(const MPSCCChan&);
                    547:        static void SetCR5(MPSCCChan&, uint32 data);
                    548:        static uint8 GetCR5(const MPSCCChan&);
1.1       root      549:        uint8 GetSR2B() const;
                    550:        void WriteCR3(MPSCCChan&, uint32 data);
                    551:        void WriteCR4(MPSCCChan&, uint32 data);
                    552:        void WriteCR5(MPSCCChan&, uint32 data);
                    553:        void WriteCR6(MPSCCChan&, uint32 data);
                    554:        void WriteCR7(MPSCCChan&, uint32 data);
                    555: 
                    556:        uint8 ReadData(MPSCCChan&);
                    557:        void WriteData(MPSCCChan&, uint32 data);
                    558:        uint8 PeekData(const MPSCCChan&) const;
                    559: 
                    560:        void SendAbort(MPSCCChan&);
                    561:        void ResetESIntr(MPSCCChan&);
                    562:        void EnableIntrOnNextRx(MPSCCChan&);
                    563:        void ResetTxIntrPending(MPSCCChan&);
                    564:        void ErrorReset(MPSCCChan&);
                    565:        void ResetHighestIUS(MPSCCChan&);
                    566: 
                    567:        // 1バイト送信
                    568:        virtual void Tx(int ch, uint32 data) = 0;
                    569: 
                    570:        // シリアルから1バイト受信のメッセージとイベントコールバック
1.1.1.7   root      571:        void HostRxCallback(uint32);
1.1.1.4   root      572:        void RxMessage(MessageID, uint32);
1.1.1.8   root      573:        void RxCallback(Event *);
1.1       root      574: 
                    575:        // 送受信関連
                    576:        void TrySend(MPSCCChan&);
                    577:        void SetTxPeriod(MPSCCChan&);
                    578:        void SetRxPeriod(MPSCCChan&);
1.1.1.8   root      579:        void TxCallback(Event *);
1.1       root      580: 
                    581:        // 割り込み
                    582:        void ChangeInterrupt();
                    583:        // ペンディングのうち最も優先度の高い割り込み要因 (VS_*) を返す
                    584:        virtual uint GetHighestInt() const = 0;
                    585: 
                    586:        // "9600,N,8,1" みたいなのを返す
                    587:        std::string GetParamStr(const MPSCCChan& chan) const;
                    588: 
1.1.1.2   root      589:        void ChangeBaudrate(MPSCCChan&);
                    590:        static int GetClkRate(uint8);
                    591:        int AdditionalBits(MPSCCChan&, bool enable);
                    592:        int GetStopBits(MPSCCChan&, bool enable);
                    593: 
1.1       root      594:        // モニタの下請け
1.1.1.9 ! root      595:        int MonitorScreenCR345(TextScreen&, int x, int y, uint8, uint8, uint8);
        !           596:        void MonitorScreenSR1(TextScreen&, int x, int y, uint8 sr1);
1.1       root      597:        void MonitorReg(TextScreen&, int x, int y,
                    598:                uint32 reg, const char * const *names);
                    599: 
                    600:        MPSCC mpscc {};
                    601: 
                    602:        // 送受信用イベント
1.1.1.8   root      603:        std::array<Event *, 2> txevent {};
                    604:        std::array<Event *, 2> rxevent {};
1.1       root      605: 
                    606:        // シリアルポート。
                    607:        // 本当は共通層でやることではないがどう考えても同じコードになるので。
                    608:        std::unique_ptr<HostCOMDevice> hostcom /*{}*/;
                    609: 
                    610:        // SR0 のログ対策 (sio.cpp::ReadCtrl 参照)
                    611:        int    sr0_logphase {};
                    612:        uint32 sr0_lastread {};
1.1.1.3   root      613: 
                    614:        InterruptDevice *interrupt {};
                    615: 
1.1.1.6   root      616:        // モニタ
                    617:        Monitor *monitor {};
1.1       root      618: };

unix.superglobalmegacorp.com

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