--- nono/vm/upd7201.h 2026/04/29 17:05:03 1.1.1.9 +++ nono/vm/upd7201.h 2026/04/29 17:05:07 1.1.1.10 @@ -7,7 +7,9 @@ #pragma once #include "device.h" +#include "event.h" #include "monitor.h" +#include // uPD7201/Z8530 のレジスタ // @@ -263,15 +265,17 @@ 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]; @@ -290,37 +294,70 @@ class uPD7201Device : public IODevice bool Rx(int ch, uint32 data); protected: - 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]; - - 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); + static const int clkrate[4]; private: - 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]; };