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

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

unix.superglobalmegacorp.com

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