--- nono/vm/mpscc.h 2026/04/29 17:05:10 1.1.1.1 +++ nono/vm/mpscc.h 2026/04/29 17:05:45 1.1.1.7 @@ -13,7 +13,6 @@ #include "device.h" #include "event.h" #include "message.h" -#include "monitor.h" #include #if defined(MPSCC_SIO_LOG_HACK) @@ -29,6 +28,7 @@ #endif class HostCOMDevice; +class InterruptDevice; // 1チャンネル分の共通部分 class MPSCCChan @@ -94,17 +94,37 @@ class MPSCCChan // これらのレジスタは uPD7201/Z8530 で共通 - // cr3 は RX_EN 以外のビットを保持。RX_EN は rx_enable で管理。 - // cr5 も TX_EN 以外のビットを保持。TX_EN は tx_enable で管理。 + // CR3/WR3 付近 + uint rxbits {}; // 受信データビット数 (レジスタ値ではない) + uint8 cr3_sync {}; // SyncMode でだけ使う bit4-1 を保存 + bool auto_enable {}; bool rx_enable {}; + + // CR4/WR4 付近 + uint clkrate {}; // クロック倍率 (レジスタ値ではない) + uint8 syncmode {}; // bit5,4 を保存 + uint8 stopbits {}; // STOPBITS_* + bool parity_even {}; + int parity_enable {}; // パリティ有効 (追加するビット数 0 か 1 で保持) + + // CR5/WR5 付近 + bool nDTR {}; // ~DTR + uint txbits {}; // 送信データビット数 (レジスタ値ではない) + bool sendbreak {}; bool tx_enable {}; - uint8 cr3 {}; - uint8 cr4 {}; - uint8 cr5 {}; + bool crc16 {}; + bool nRTS {}; // ~RTS + bool txcrc_en {}; + uint8 cr6 {}; uint8 cr7 {}; uint8 sr1 {}; + // いずれもレジスタイメージとして保存 + uint8 old_cr3 {}; + uint8 old_cr4 {}; + uint8 old_cr5 {}; + // Z8530 専用のレジスタだけど継承とかは面倒なので結局ここに置く uint8 wr10 {}; uint8 wr11 {}; @@ -154,8 +174,16 @@ class MPSCCChan double baudrate {}; // 1フレームあたりの送受信のビット数 (表示用) - int txbits {}; - int rxbits {}; + uint txframebits {}; + uint rxframebits {}; + + // LUNA の場合は TxC, RxC ピンに供給されているクロック。 + // X68030 の場合は Z8530 内部で生成されている基準クロック。 + // 誤差を減らすため 12 ビット分の時間 [nsec] としている。 + uint64 xc12_ns {}; + + // 実際の 12 ビットの通信にかかる時間。xc12_ns に倍率をかけたもの。 + uint64 bit12_ns {}; }; class MPSCC @@ -244,6 +272,7 @@ class MPSCC // static const uint8 CR3_RXBITS = 0xc0; // Rx Bits static const uint8 CR3_AUTO_EN = 0x40; // Auto Enable + static const uint8 CR3_SYNC_MASK = 0x1e; static const uint8 CR3_RX_EN = 0x01; // Rx Enable // WR3 static const uint8 WR3_RXBITS = CR3_RXBITS; @@ -278,10 +307,15 @@ class MPSCC static const uint8 WR4_PARITY_EVEN = CR4_PARITY_EVEN; static const uint8 WR4_PARITY_EN = CR4_PARITY_EN; - static const uint8 STOPBITS_SYNC = 0x00; - static const uint8 STOPBITS_1 = 0x04; - static const uint8 STOPBITS_1_5 = 0x08; - static const uint8 STOPBITS_2 = 0x0c; + static const uint8 CLKRATE_1 = 0x00; + static const uint8 CLKRATE_16 = 0x40; + static const uint8 CLKRATE_32 = 0x80; + static const uint8 CLKRATE_64 = 0xc0; + + static const uint8 STOPBITS_SYNC = (0x00 >> 2); + static const uint8 STOPBITS_1 = (0x04 >> 2); + static const uint8 STOPBITS_1_5 = (0x08 >> 2); + static const uint8 STOPBITS_2 = (0x0c >> 2); // b7 b6 b5 b4 b3 b2 b1 b0 // +----+---------+----+----+----+----+----+ @@ -476,7 +510,7 @@ class MPSCCDevice : public IODevice static const int COM_CH = 0; public: - MPSCCDevice(const std::string& objname_); + MPSCCDevice(); ~MPSCCDevice() override; bool Create() override; @@ -488,8 +522,8 @@ class MPSCCDevice : public IODevice protected: // 指定のレジスタ名を返す - virtual const char *CRName(const MPSCCChan&, int n) const = 0; - virtual const char *SRName(const MPSCCChan&, int n) const = 0; + virtual const char *CRName(const MPSCCChan&, uint n) const = 0; + virtual const char *SRName(const MPSCCChan&, uint n) const = 0; // 現在のレジスタ名を返す const char *CRName(const MPSCCChan& chan) const { return CRName(chan, chan.ptr); @@ -501,10 +535,18 @@ class MPSCCDevice : public IODevice // チャンネルリセットの共通部 void ResetChannelCommon(MPSCCChan&); + // BusIO インタフェース + static const uint32 NPORT = 4; + bool PokePort(uint32 offset, uint32 data); + // レジスタアクセス - uint8 GetCR0(const MPSCCChan&) const; - uint8 GetCR3(const MPSCCChan&) const; - uint8 GetCR5(const MPSCCChan&) const; + static uint8 GetCR0(const MPSCCChan&); + static void SetCR3(MPSCCChan&, uint32 data); + static uint8 GetCR3(const MPSCCChan&); + static void SetCR4(MPSCCChan&, uint32 data); + static uint8 GetCR4(const MPSCCChan&); + static void SetCR5(MPSCCChan&, uint32 data); + static uint8 GetCR5(const MPSCCChan&); uint8 GetSR2B() const; void WriteCR3(MPSCCChan&, uint32 data); void WriteCR4(MPSCCChan&, uint32 data); @@ -527,8 +569,8 @@ class MPSCCDevice : public IODevice virtual void Tx(int ch, uint32 data) = 0; // シリアルから1バイト受信のメッセージとイベントコールバック - void HostRxCallback(); - void RxMessageCallback(MessageID, uint32); + void HostRxCallback(uint32); + void RxMessage(MessageID, uint32); void RxCallback(Event&); // 送受信関連 @@ -545,6 +587,11 @@ class MPSCCDevice : public IODevice // "9600,N,8,1" みたいなのを返す std::string GetParamStr(const MPSCCChan& chan) const; + void ChangeBaudrate(MPSCCChan&); + static int GetClkRate(uint8); + int AdditionalBits(MPSCCChan&, bool enable); + int GetStopBits(MPSCCChan&, bool enable); + // モニタの下請け int MonitorUpdateCR345(TextScreen&, int x, int y, uint8, uint8, uint8); void MonitorUpdateSR1(TextScreen&, int x, int y, uint8 sr1); @@ -553,10 +600,6 @@ class MPSCCDevice : public IODevice MPSCC mpscc {}; - // TxC, RxC ピンに供給されているクロックで 12ビットの通信にかかる - // 時間を ns 単位で設定。12 ビットは誤差を減らすために選択。 - uint64 xc12_ns {}; - // 送受信用イベント std::array txevent {}; std::array rxevent {}; @@ -565,16 +608,12 @@ class MPSCCDevice : public IODevice // 本当は共通層でやることではないがどう考えても同じコードになるので。 std::unique_ptr hostcom /*{}*/; - // モニタ (更新関数は継承側で用意する) - Monitor monitor { this }; - // SR0 のログ対策 (sio.cpp::ReadCtrl 参照) int sr0_logphase {}; uint32 sr0_lastread {}; - static const int bits_per_char[4]; - static const int clkrates[4]; + InterruptDevice *interrupt {}; - private: - std::string SetPeriod(MPSCCChan&, bool enable, int *bit, uint64 *evtime); + // モニタ + Monitor *monitor {}; };