--- nono/vm/upd7201.h 2026/04/29 17:04:28 1.1 +++ nono/vm/upd7201.h 2026/04/29 17:05:03 1.1.1.9 @@ -1,11 +1,13 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #pragma once #include "device.h" +#include "monitor.h" // uPD7201/Z8530 のレジスタ // @@ -23,8 +25,10 @@ // 用意するほうが楽なので、こうなっている。 struct SIO { - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +---------+--------------+--------------+ // CR0 | CRC | Command | Pointer | + // +---------+--------------+--------------+ static const int CR0_CRC = 0xc0; static const int CR0_CMD = 0x38; static const int CR0_PTR = 0x07; @@ -35,8 +39,10 @@ struct SIO static const int WR0_CMD = CR0_CMD; static const int WR0_PTR = 0x0f; - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +----+----+----+---------+----+----+----+ // CR1 | WE | -- | WR | RX Int | -- | TE | ES | + // +----+----+----+---------+----+----+----+ // | | | | +---- E/S Int Enable // | | | +--------- TX INT/DMA Enable // | | +--------------------- RX Int Mode @@ -60,8 +66,10 @@ struct SIO static const int RXINT_ALL_INC_SPECIAL = 0x10; // All char include special static const int RXINT_ALL_EXC_SPECIAL = 0x18; // All char exclude special - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +---------+----+-------------------+----+ // CR3 | RX bits | AE | -- -- -- -- | RE | + // +---------+----+-------------------+----+ // | | +---- RX Enable // | +----------------------------- Auto Enable // +------------------------------------ RX bits @@ -73,14 +81,16 @@ struct SIO static const int WR3_AUTO_EN = CR3_AUTO_EN; static const int WR3_RX_EN = CR3_RX_EN; - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +---------+---------+---------+----+----+ // CR4 | ClkRate | SyncMode| StopBits| PV | PE | + // +---------+---------+---------+----+----+ // | | | | +---- Parity Enable(%1) // | | | +--------- Parity Even(%1) // | | +---------------- Stop Bits // | +-------------------------- Sync Mode // +------------------------------------ Clock Rate - // + // static const int CR4_CLKRATE = 0xc0; static const int CR4_SYNCMODE = 0x30; static const int CR4_STOPBITS = 0x0c; @@ -109,8 +119,10 @@ struct SIO HDLC = 2, }; - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +----+---------+----+----+----+----+----+ // CR5 | DTR| TX bits | SB | TE | CRC| RTS| TC | + // +----+---------+----+----+----+----+----+ // | | | | | | +---- TX CRC Enable // | | | | | +--------- ~RTS // | | | | +-------------- CRC-16/CCITT @@ -134,8 +146,10 @@ struct SIO static const int WR5_RTS = CR5_RTS; static const int WR5_TXCRC_EN = CR5_TXCRC_EN; - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +----+----+----+----+----+----+----+----+ // SR0 | BA | TU | CTS| SY | DCD| TE | IP | RA | + // +----+----+----+----+----+----+----+----+ static const int SR0_BREAK = 0x80; // Break/Abort static const int SR0_TXUNDER = 0x40; // Tx Underrun static const int SR0_CTS = 0x20; // CTS @@ -154,8 +168,10 @@ struct SIO static const int RR0_INTPEND = SR0_INTPEND; static const int RR0_RXAVAIL = SR0_RXAVAIL; - // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // b7 b6 b5 b4 b3 b2 b1 b0 + // +----+----+----+----+--------------+----+ // SR1 | EF | CRC| RO | PE | ResidueCode | AS | + // +----+----+----+----+--------------+----+ static const int SR1_ENDOFFRAME = 0x80; // End of Frame static const int SR1_CRCERROR = 0x40; // CRC/Framing Error static const int SR1_RXOVERRUN = 0x20; // Rx Overrun @@ -170,6 +186,43 @@ struct SIO static const int RR1_RESIDUEMASK= SR1_RESIDUEMASK; static const int RR1_ALL_SENT = SR1_ALL_SENT; + // 割り込みベクタ ChB ChA + // Tx Buffer Empty %000 %100 + // External/Status Change %001 %101 + // Rx Character Available %010 %110 + // Special Rx Condition %011 %111 + // (この 3bit が V4-V2 か V2-V0 のところに出力される) + static const uint INTR_TX = (1U << 0); + static const uint INTR_ES = (1U << 1); + static const uint INTR_RX = (1U << 2); + static const uint INTR_SP = (1U << 3); + + // 割り込みあたりのロジック (uPD7201/7201A Figure 3-2 より INT 分のみ) + // + // Rx Disable (CR1:b1) *1 -----------------+ *1: Rx Enable (CR3:b0) + // | じゃなくて? + // +---+ | + // * RxCharAvailable ---->| | | + // | AND )--+ | +---+ + // All/First RxChar --->| | | +---+ +->| | + // +---+ +->) | | AND )--+ + // ) OR )-->| | | + // * Special Rx Condition ----------->) | +---+ | +-+ + // +---+ +->) | + // ) | --- + // * External/Status -------------------------------------->) OR |o-> INT + // ) | + // +---+ +->) | + // * Tx Buffer Empty ---------------->| | +----+ | +-+ + // | | | | | + // (Reset TxIntPend Cmd) --------->o| AND )-->| | | + // | | | | | + // Tx INT/DMA Enable (CR1:b1) ----->| | | AND )--+ + // +---+ | | + // | | + // INT DMA Mode (CR2A b1-0) ----------------->| | + // +----+ + int cr2a; // CR2A int vector; struct channel { @@ -181,6 +234,8 @@ struct SIO Mode mode; // CR4 で決まるモード // uPD7201 レジスタ + // CR0 の下位 3bit (PTR 部分) は読み出し時には使わないこと (代わりに + // ptr を使用する)。書き込み時は書き込んでよい(書き捨て)。 uint8 cr0; uint8 cr1; // CR2 は特殊なのでここにはない @@ -194,6 +249,7 @@ struct SIO uint8 sr1; // ここから Z8530 拡張 + uint8 wr10; // WR10 uint8 wr11; // WR11 uint16 tc; // WR12, WR13 uint8 wr14; // WR14 @@ -206,41 +262,65 @@ struct SIO // 取り出したら前にずらす? uint8 rxbuf[3]; // 受信バッファ(FIFO) int rxlen; // 受信バッファの有効バイト数 - bool rxrecved; // 1文字でも受信したら true (FirstCharIntr用) + + // First Char 用のフラグで、この受信で割り込みを起こすなら true。 + // ALL なら常に true。FIRSTCHAR の時は最初が true で1文字目の受信 + // 割り込みを出したところで false にする。 + bool all_or_first; + + // Reset Tx Interrupt/DMA Pending コマンドによる Tx 割り込み抑制。 + // 通常 true にしておき、コマンドが発行されたら false にする。 + // XXX 解除するのはリセットでええんかな? + bool reset_txint_pend; + + uint int_asserted; // 割り込み要因を保持 } chan[2]; }; -class uPD7201Device - : public IODevice +class uPD7201Device : public IODevice { - typedef IODevice inherited; + using inherited = IODevice; public: - uPD7201Device(); - virtual ~uPD7201Device(); + uPD7201Device(const std::string& objname_); + virtual ~uPD7201Device() override; - virtual bool MonitorUpdate(); + void ResetHard() override; // 受信 bool Rx(int ch, uint32 data); protected: - // チップリセット - void Reset(); - void ResetChannel(struct SIO::channel *chan); virtual uint8 ReadCtrl(struct SIO::channel *chan); - uint8 ReadData(int ch); + uint8 ReadData(struct SIO::channel *chan); virtual void WriteCtrl(struct SIO::channel *chan, uint32 data); void WriteData(struct SIO::channel *chan, uint32 data); + uint8 PeekCtrl(const struct SIO::channel *chan) const; + uint8 PeekData(const struct SIO::channel *chan) const; // 割り込みを上げる (上位デバイスで用意する) virtual void Interrupt() = 0; struct SIO cr {}; + Monitor monitor { this }; + static const int bits_per_char[4]; + void WriteCR0(struct SIO::channel *chan, uint32 data); + void WriteCR1(struct SIO::channel *chan, uint32 data); + void WriteCR2(struct SIO::channel *chan, uint32 data); + void WriteCR3(struct SIO::channel *chan, uint32 data); + void WriteCR4(struct SIO::channel *chan, uint32 data); + virtual void WriteCR5(struct SIO::channel *chan, uint32 data); + void WriteCR6(struct SIO::channel *chan, uint32 data); + void WriteCR7(struct SIO::channel *chan, uint32 data); + private: - void MonitorUpdateCh(int ch, int xbase, int ybase); - void MonitorReg(int, int, uint32 reg, const char * const *names); + void ChangeInterrupt(); + + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + void MonitorUpdateCh(TextScreen&, int ch, int xbase, int ybase); + void MonitorReg(TextScreen&, + int, int, uint32 reg, const char * const *names); };