--- nono/vm/upd7201.h 2026/04/29 17:04:50 1.1.1.6 +++ nono/vm/upd7201.h 2026/04/29 17:05:07 1.1.1.10 @@ -7,6 +7,9 @@ #pragma once #include "device.h" +#include "event.h" +#include "monitor.h" +#include // uPD7201/Z8530 のレジスタ // @@ -24,8 +27,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; @@ -36,8 +41,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 @@ -61,8 +68,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 @@ -74,8 +83,10 @@ 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 @@ -110,8 +121,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 @@ -135,8 +148,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 @@ -155,8 +170,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 @@ -248,66 +265,99 @@ struct SIO uint8 rxbuf[3]; // 受信バッファ(FIFO) int rxlen; // 受信バッファの有効バイト数 + uint8 txbuf; // 送信バッファ + int txlen; // 送信バッファの有効バイト数 + uint8 tx_shiftreg; // 送信シフトレジスタ相当品 + // 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; + // 送信割り込み + bool txint; uint int_asserted; // 割り込み要因を保持 } chan[2]; }; -class uPD7201Device - : public IODevice +class uPD7201Device : public IODevice { using inherited = IODevice; public: - uPD7201Device(); + uPD7201Device(const std::string& objname_); virtual ~uPD7201Device() override; void ResetHard() override; - void MonitorUpdate(TextScreen&) 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(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; + void ResetChannel(SIO::channel *chan); + virtual uint8 ReadCtrl(SIO::channel *chan); + uint8 ReadData(SIO::channel *chan); + virtual void WriteCtrl(SIO::channel *chan, uint32 data); + void WriteData(SIO::channel *chan, uint32 data); + uint8 PeekCtrl(const SIO::channel *chan) const; + uint8 PeekData(const SIO::channel *chan) const; + + virtual void WriteCR0(SIO::channel *chan, uint32 data); + void SendAbort(SIO::channel *chan); + void ResetESIntr(SIO::channel *chan); + void EnableIntrOnNextRx(SIO::channel *chan); + void ResetTxIntrPending(SIO::channel *chan); + void ErrorReset(SIO::channel *chan); + void ResetHighestIUS(SIO::channel *chan); + void WriteCR1(SIO::channel *chan, uint32 data); + void WriteCR2(SIO::channel *chan, uint32 data); + void WriteCR3(SIO::channel *chan, uint32 data); + void WriteCR4(SIO::channel *chan, uint32 data); + virtual void WriteCR5(SIO::channel *chan, uint32 data); + void WriteCR6(SIO::channel *chan, uint32 data); + void WriteCR7(SIO::channel *chan, uint32 data); + + void TrySend(SIO::channel *chan); + void TXCallback(Event& event); + virtual void Tx(int ch, uint32 data) = 0; + void ChangeInterrupt(); // 割り込みを上げる (上位デバイスで用意する) virtual void Interrupt() = 0; + // 指定のレジスタ名を返す + virtual const char *CRName(const SIO::channel *chan, int n) const; + virtual const char *SRName(const SIO::channel *chan, int n) const; + // 現在のレジスタ名を返す + const char *CRName(const SIO::channel *chan) const { + return CRName(chan, chan->ptr); + } + const char *SRName(const SIO::channel *chan) const { + return SRName(chan, chan->ptr); + } + struct SIO cr {}; + // TxC ピンに供給されているクロックで 12ビットの通信にかかる + // 時間を ns 単位で設定。12 ビットは誤差を減らすために選択。 + uint64 txc12_ns {}; + + // 送信用イベント + std::array txevent {}; + + Monitor monitor { this }; + static const int bits_per_char[4]; + static const int clkrate[4]; private: - 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); - void WriteCR5(struct SIO::channel *chan, uint32 data); - void WriteCR6(struct SIO::channel *chan, uint32 data); - void WriteCR7(struct SIO::channel *chan, uint32 data); - - void ChangeInterrupt(); + void SetTXPeriod(SIO::channel *chan); + DECLARE_MONITOR_CALLBACK(MonitorUpdate); void MonitorUpdateCh(TextScreen&, int ch, int xbase, int ybase); void MonitorReg(TextScreen&, int, int, uint32 reg, const char * const *names); + + static const char * const crnames[16]; + static const char * const srnames[16]; };