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

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

unix.superglobalmegacorp.com

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