Annotation of nono/vm/upd7201.h, revision 1.1.1.8

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #pragma once
                      8: 
                      9: #include "device.h"
1.1.1.7   root       10: #include "monitor.h"
1.1       root       11: 
                     12: // uPD7201/Z8530 のレジスタ
                     13: //
                     14: // uPD7201 は、書き込みが CR (Command Register) 8本、
                     15: // 読み込みが SR (Status Register) 2本。
                     16: // Z8530 は、書き込みが WR (Write Register) 16本、
                     17: // 読み込みが RR (Read Register) 8本。
                     18: //
                     19: // Z8530 の WR0..WR7、RR0..RR2 は (名前が異なるが)
                     20: // uPD7201 の CR0..CR7、SR0..SR2 とわりとよく似ている (所々違う)。
                     21: //
                     22: // そのためデバイスは uPD7201Device クラスを基底に、SIODevice
                     23: // (ほぼ uPD7201Device) と SCCDevice (Z8530) とに派生している。
                     24: // レジスタ構造体は C++ の制約的に両方のセットを持ったものを一つ
                     25: // 用意するほうが楽なので、こうなっている。
                     26: struct SIO
                     27: {
1.1.1.8 ! root       28:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !            29:        //     +---------+--------------+--------------+
1.1       root       30:        // CR0 |   CRC   |   Command    |   Pointer    |
1.1.1.8 ! root       31:        //     +---------+--------------+--------------+
1.1       root       32:        static const int CR0_CRC                = 0xc0;
                     33:        static const int CR0_CMD                = 0x38;
                     34:        static const int CR0_PTR                = 0x07;
                     35: 
                     36:        // Z8530 ではコマンド %000 と %001 がレジスタ切り替えなので、
                     37:        // CMD が 0x38、PTR が 0x0f とあえて被せてある。
                     38:        static const int WR0_CRC                = CR0_CRC;
                     39:        static const int WR0_CMD                = CR0_CMD;
                     40:        static const int WR0_PTR                = 0x0f;
                     41: 
1.1.1.8 ! root       42:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !            43:        //     +----+----+----+---------+----+----+----+
1.1       root       44:        // CR1 | WE | -- | WR |  RX Int | -- | TE | ES |
1.1.1.8 ! root       45:        //     +----+----+----+---------+----+----+----+
1.1       root       46:        //       |         |       |           |    +---- E/S Int Enable
                     47:        //       |         |       |           +--------- TX INT/DMA Enable
                     48:        //       |         |       +--------------------- RX Int Mode
                     49:        //       |         +----------------------------- Wait on RX(=%1),TX(=%0)
                     50:        //       +--------------------------------------- Wait Enable
                     51:        static const int CR1_WAIT_EN    = 0x80;
                     52:        static const int CR1_WAIT_RX    = 0x20;
                     53:        static const int CR1_RXINT              = 0x18;
                     54:        static const int CR1_TXINT_EN   = 0x02;
                     55:        static const int CR1_ESINT_EN   = 0x01;
                     56: 
                     57:        static const int WR1_WAIT_EN    = CR1_WAIT_EN;
                     58:        static const int WR1_WAIT_RX    = CR1_WAIT_RX;
                     59:        static const int WR1_RXINT              = CR1_RXINT;
                     60:        static const int WR1_TXINT_EN   = CR1_TXINT_EN;
                     61:        static const int WR1_ESINT_EN   = CR1_ESINT_EN;
                     62: 
                     63:        // CR1_RXINT
                     64:        static const int RXINT_DISABLE                  = 0x00; // disabled
                     65:        static const int RXINT_FIRSTCHAR                = 0x08; // First charactoer intr.
                     66:        static const int RXINT_ALL_INC_SPECIAL  = 0x10; // All char include special
                     67:        static const int RXINT_ALL_EXC_SPECIAL  = 0x18; // All char exclude special
                     68: 
1.1.1.8 ! root       69:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !            70:        //     +---------+----+-------------------+----+
1.1       root       71:        // CR3 | RX bits | AE | --   --   --   -- | RE |
1.1.1.8 ! root       72:        //     +---------+----+-------------------+----+
1.1       root       73:        //          |      |                        +---- RX Enable
                     74:        //          |      +----------------------------- Auto Enable
                     75:        //          +------------------------------------ RX bits
                     76:        static const int CR3_RXBITS             = 0xc0;
                     77:        static const int CR3_AUTO_EN    = 0x40;
                     78:        static const int CR3_RX_EN              = 0x01;
                     79: 
                     80:        static const int WR3_RXBITS             = CR3_RXBITS;
                     81:        static const int WR3_AUTO_EN    = CR3_AUTO_EN;
                     82:        static const int WR3_RX_EN              = CR3_RX_EN;
                     83: 
1.1.1.8 ! root       84:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !            85:        //     +---------+---------+---------+----+----+
1.1       root       86:        // CR4 | ClkRate | SyncMode| StopBits| PV | PE |
1.1.1.8 ! root       87:        //     +---------+---------+---------+----+----+
1.1       root       88:        //          |         |         |      |    +---- Parity Enable(%1)
                     89:        //          |         |         |      +--------- Parity Even(%1)
                     90:        //          |         |         +---------------- Stop Bits
                     91:        //          |         +-------------------------- Sync Mode
                     92:        //          +------------------------------------ Clock Rate
1.1.1.6   root       93:        //
1.1       root       94:        static const int CR4_CLKRATE    = 0xc0;
                     95:        static const int CR4_SYNCMODE   = 0x30;
                     96:        static const int CR4_STOPBITS   = 0x0c;
                     97:        static const int CR4_PARITY_EVEN= 0x02;
                     98:        static const int CR4_PARITY_EN  = 0x01;
                     99: 
                    100:        static const int WR4_CLKRATE    = CR4_CLKRATE;
                    101:        static const int WR4_SYNCMODE   = CR4_SYNCMODE;
                    102:        static const int WR4_STOPBITS   = CR4_STOPBITS;
                    103:        static const int WR4_PARITY_EVEN= CR4_PARITY_EVEN;
                    104:        static const int WR4_PARITY_EN  = CR4_PARITY_EN;
                    105: 
                    106:        static const int SYNC_8BIT              = 0x00;
                    107:        static const int SYNC_16BIT             = 0x10;
                    108:        static const int SYNC_HDLC              = 0x20;
                    109:        static const int SYNC_EXT               = 0x30;
                    110: 
                    111:        static const int SYNC_MODE              = 0x00;
                    112:        static const int STOP_BITS_1    = 0x04;
                    113:        static const int STOP_BITS_1_5  = 0x08;
                    114:        static const int STOP_BITS_2    = 0x0c;
                    115: 
                    116:        enum Mode {
                    117:                SYNC = 0,
                    118:                ASYNC = 1,
                    119:                HDLC = 2,
                    120:        };
                    121: 
1.1.1.8 ! root      122:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !           123:        //     +----+---------+----+----+----+----+----+
1.1       root      124:        // CR5 | DTR| TX bits | SB | TE | CRC| RTS| TC |
1.1.1.8 ! root      125:        //     +----+---------+----+----+----+----+----+
1.1       root      126:        //       |       |      |    |    |    |    +---- TX CRC Enable
                    127:        //       |       |      |    |    |    +--------- ~RTS
                    128:        //       |       |      |    |    +-------------- CRC-16/CCITT
                    129:        //       |       |      |    +------------------- TX Enable
                    130:        //       |       |      +------------------------ Send Break
                    131:        //       |       +------------------------------- TX Bits
                    132:        //       +--------------------------------------- ~DTR
                    133:        static const int CR5_DTR                = 0x80;
                    134:        static const int CR5_TXBITS             = 0x60;
                    135:        static const int CR5_SENDBREAK  = 0x10;
                    136:        static const int CR5_TX_EN              = 0x08;
                    137:        static const int CR5_CRC16              = 0x04;
                    138:        static const int CR5_RTS                = 0x02;
                    139:        static const int CR5_TXCRC_EN   = 0x01;
                    140: 
                    141:        static const int WR5_DTR                = CR5_DTR;
                    142:        static const int WR5_TXBITS             = CR5_TXBITS;
                    143:        static const int WR5_SENDBREAK  = CR5_SENDBREAK;
                    144:        static const int WR5_TX_EN              = CR5_TX_EN;
                    145:        static const int WR5_CRC16              = CR5_CRC16;
                    146:        static const int WR5_RTS                = CR5_RTS;
                    147:        static const int WR5_TXCRC_EN   = CR5_TXCRC_EN;
                    148: 
1.1.1.8 ! root      149:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !           150:        //     +----+----+----+----+----+----+----+----+
1.1       root      151:        // SR0 | BA | TU | CTS| SY | DCD| TE | IP | RA |
1.1.1.8 ! root      152:        //     +----+----+----+----+----+----+----+----+
1.1       root      153:        static const int SR0_BREAK              = 0x80; // Break/Abort
                    154:        static const int SR0_TXUNDER    = 0x40; // Tx Underrun
                    155:        static const int SR0_CTS                = 0x20; // CTS
                    156:        static const int SR0_SYNC               = 0x10; // SYNC
                    157:        static const int SR0_DCD                = 0x08; // DCD
                    158:        static const int SR0_TXEMPTY    = 0x04; // Tx Buffer Empty
                    159:        static const int SR0_INTPEND    = 0x02; // Interrupt Pending
                    160:        static const int SR0_RXAVAIL    = 0x01; // Rx Character Available
                    161: 
                    162:        static const int RR0_BREAK              = SR0_BREAK;
                    163:        static const int RR0_TXUNDER    = SR0_TXUNDER;
                    164:        static const int RR0_CTS                = SR0_CTS;
                    165:        static const int RR0_SYNC               = SR0_SYNC;
                    166:        static const int RR0_DCD                = SR0_DCD;
                    167:        static const int RR0_TXEMPTY    = SR0_TXEMPTY;
                    168:        static const int RR0_INTPEND    = SR0_INTPEND;
                    169:        static const int RR0_RXAVAIL    = SR0_RXAVAIL;
                    170: 
1.1.1.8 ! root      171:        //       b7   b6   b5   b4   b3   b2   b1   b0
        !           172:        //     +----+----+----+----+--------------+----+
1.1       root      173:        // SR1 | EF | CRC| RO | PE | ResidueCode  | AS |
1.1.1.8 ! root      174:        //     +----+----+----+----+--------------+----+
1.1       root      175:        static const int SR1_ENDOFFRAME = 0x80; // End of Frame
                    176:        static const int SR1_CRCERROR   = 0x40; // CRC/Framing Error
                    177:        static const int SR1_RXOVERRUN  = 0x20; // Rx Overrun
                    178:        static const int SR1_PARITYERROR= 0x10; // Parity Error
                    179:        static const int SR1_RESIDUEMASK= 0x0e; // Residue Code 2-0
                    180:        static const int SR1_ALL_SENT   = 0x01; // All Sent
                    181: 
                    182:        static const int RR1_ENDOFFRAME = SR1_ENDOFFRAME;
                    183:        static const int RR1_CRCERROR   = SR1_CRCERROR;
                    184:        static const int RR1_RXOVERRUN  = SR1_RXOVERRUN;
                    185:        static const int RR1_PARITYERROR= SR1_PARITYERROR;
                    186:        static const int RR1_RESIDUEMASK= SR1_RESIDUEMASK;
                    187:        static const int RR1_ALL_SENT   = SR1_ALL_SENT;
                    188: 
1.1.1.5   root      189:        // 割り込みベクタ          ChB   ChA
                    190:        // Tx Buffer Empty         %000  %100
                    191:        // External/Status Change  %001  %101
                    192:        // Rx Character Available  %010  %110
                    193:        // Special Rx Condition    %011  %111
                    194:        // (この 3bit が V4-V2 か V2-V0 のところに出力される)
                    195:        static const uint INTR_TX       = (1U << 0);
                    196:        static const uint INTR_ES       = (1U << 1);
                    197:        static const uint INTR_RX       = (1U << 2);
                    198:        static const uint INTR_SP       = (1U << 3);
                    199: 
                    200:        // 割り込みあたりのロジック (uPD7201/7201A Figure 3-2 より INT 分のみ)
                    201:        //
                    202:        //   Rx Disable (CR1:b1) *1 -----------------+    *1: Rx Enable (CR3:b0)
                    203:        //                                           |        じゃなくて?
                    204:        //                        +---+              |
                    205:        // * RxCharAvailable ---->|    |             |
                    206:        //                        | AND )--+         |  +---+
                    207:        //   All/First RxChar --->|    |   |  +---+  +->|    |
                    208:        //                        +---+    +->)    |    | AND )--+
                    209:        //                                    ) OR  )-->|    |   |
                    210:        // * Special Rx Condition ----------->)    |    +---+    |  +-+
                    211:        //                                    +---+              +->)  |
                    212:        //                                                          )   |     ---
                    213:        // * External/Status -------------------------------------->) OR |o-> INT
                    214:        //                                                          )   |
                    215:        //                                    +---+              +->)  |
                    216:        // * Tx Buffer Empty ---------------->|    |    +----+   |  +-+
                    217:        //                                    |    |    |    |   |
                    218:        //   (Reset TxIntPend Cmd) --------->o| AND )-->|    |   |
                    219:        //                                    |    |    |    |   |
                    220:        //   Tx INT/DMA Enable (CR1:b1) ----->|    |    | AND )--+
                    221:        //                                    +---+     |    |
                    222:        //                                              |    |
                    223:        //   INT DMA Mode (CR2A b1-0) ----------------->|    |
                    224:        //                                              +----+
                    225: 
1.1       root      226:        int cr2a;                       // CR2A
                    227:        int vector;
                    228:        struct channel {
                    229:                // 二次変数など
                    230:                int ptr;                        // CR0 で決まるレジスタ選択ポインタ
                    231:                int id;                         // チャンネル番号。0 か 1
                    232:                const char *name;       // チャンネル名。"A" か "B"
                    233:                const char *desc;       // チャンネルの用途(モニタ表示用)
                    234:                Mode mode;                      // CR4 で決まるモード
                    235: 
                    236:                // uPD7201 レジスタ
1.1.1.5   root      237:                // CR0 の下位 3bit (PTR 部分) は読み出し時には使わないこと (代わりに
                    238:                // ptr を使用する)。書き込み時は書き込んでよい(書き捨て)。
1.1       root      239:                uint8 cr0;
                    240:                uint8 cr1;
                    241:                                                        // CR2 は特殊なのでここにはない
                    242:                uint8 cr3;
                    243:                uint8 cr4;
                    244:                uint8 cr5;
                    245:                uint8 cr6;                      // CR6 (未実装)
                    246:                uint8 cr7;                      // CR7 (未実装)
                    247: 
                    248:                uint8 sr0;
                    249:                uint8 sr1;
                    250: 
                    251:                // ここから Z8530 拡張
1.1.1.5   root      252:                uint8 wr10;                     // WR10
1.1       root      253:                uint8 wr11;                     // WR11
                    254:                uint16 tc;                      // WR12, WR13
                    255:                uint8 wr14;                     // WR14
                    256:                uint8 wr15;                     // WR15
                    257: 
                    258:                // ここからその他の内部状態
                    259:                bool es_ratched;        // E/S ビットがラッチされているか
                    260: 
                    261:                // 受信バッファは短いので先頭からの FIFO とし、
                    262:                // 取り出したら前にずらす?
                    263:                uint8 rxbuf[3];         // 受信バッファ(FIFO)
                    264:                int   rxlen;            // 受信バッファの有効バイト数
1.1.1.5   root      265: 
                    266:                // First Char 用のフラグで、この受信で割り込みを起こすなら true。
                    267:                // ALL なら常に true。FIRSTCHAR の時は最初が true で1文字目の受信
                    268:                // 割り込みを出したところで false にする。
                    269:                bool all_or_first;
                    270: 
                    271:                // Reset Tx Interrupt/DMA Pending コマンドによる Tx 割り込み抑制。
                    272:                // 通常 true にしておき、コマンドが発行されたら false にする。
                    273:                // XXX 解除するのはリセットでええんかな?
                    274:                bool reset_txint_pend;
                    275: 
                    276:                uint int_asserted;      // 割り込み要因を保持
1.1       root      277:        } chan[2];
                    278: };
                    279: 
1.1.1.7   root      280: class uPD7201Device : public IODevice
1.1       root      281: {
1.1.1.3   root      282:        using inherited = IODevice;
1.1       root      283:  public:
1.1.1.7   root      284:        uPD7201Device(const std::string& objname_);
1.1.1.5   root      285:        virtual ~uPD7201Device() override;
1.1       root      286: 
1.1.1.6   root      287:        void ResetHard() override;
1.1       root      288: 
                    289:        // 受信
                    290:        bool Rx(int ch, uint32 data);
                    291: 
                    292:  protected:
                    293:        // チップリセット
                    294:        void Reset();
                    295: 
                    296:        void ResetChannel(struct SIO::channel *chan);
                    297:        virtual uint8 ReadCtrl(struct SIO::channel *chan);
1.1.1.2   root      298:        uint8 ReadData(struct SIO::channel *chan);
1.1       root      299:        virtual void WriteCtrl(struct SIO::channel *chan, uint32 data);
                    300:        void WriteData(struct SIO::channel *chan, uint32 data);
1.1.1.2   root      301:        uint8 PeekCtrl(const struct SIO::channel *chan) const;
                    302:        uint8 PeekData(const struct SIO::channel *chan) const;
1.1       root      303: 
                    304:        // 割り込みを上げる (上位デバイスで用意する)
                    305:        virtual void Interrupt() = 0;
                    306: 
                    307:        struct SIO cr {};
                    308: 
1.1.1.7   root      309:        Monitor monitor { this };
                    310: 
1.1       root      311:        static const int bits_per_char[4];
                    312: 
1.1.1.5   root      313:        void WriteCR0(struct SIO::channel *chan, uint32 data);
                    314:        void WriteCR1(struct SIO::channel *chan, uint32 data);
                    315:        void WriteCR2(struct SIO::channel *chan, uint32 data);
                    316:        void WriteCR3(struct SIO::channel *chan, uint32 data);
                    317:        void WriteCR4(struct SIO::channel *chan, uint32 data);
1.1.1.8 ! root      318:        virtual void WriteCR5(struct SIO::channel *chan, uint32 data);
1.1.1.5   root      319:        void WriteCR6(struct SIO::channel *chan, uint32 data);
                    320:        void WriteCR7(struct SIO::channel *chan, uint32 data);
                    321: 
1.1.1.8 ! root      322:  private:
1.1.1.5   root      323:        void ChangeInterrupt();
1.1.1.2   root      324: 
1.1.1.7   root      325:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
1.1.1.4   root      326:        void MonitorUpdateCh(TextScreen&, int ch, int xbase, int ybase);
                    327:        void MonitorReg(TextScreen&,
                    328:                int, int, uint32 reg, const char * const *names);
1.1       root      329: };

unix.superglobalmegacorp.com

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