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

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

unix.superglobalmegacorp.com

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