--- nono/vm/pio.h 2026/04/29 17:04:42 1.1.1.4 +++ nono/vm/pio.h 2026/04/29 17:06:00 1.1.1.16 @@ -4,32 +4,48 @@ // Licensed under nono-license.txt // +// +// PIO/PPI (i8255) +// + #pragma once #include "device.h" -#include "scheduler.h" +#include + +class ADPCMDevice; +class InterruptDevice; +class LCDDevice; +class MPU64180Device; +class PIO1Device; +class PowerDevice; // Intel 82C55 の仕様書にはコントロールポートからの読み出しは明記してある。 // NEC uPD8255 の仕様書にはコントロールポートからの読み出しについての記載が // ない (禁止とも書いてない)。 -class i8255Device - : public IODevice +class i8255Device : public IODevice { using inherited = IODevice; public: - i8255Device(); + explicit i8255Device(uint objid_); ~i8255Device() override; - void ResetHard() override; + void ResetHard(bool poweron) override; protected: + // BusIO インタフェース + bool PokePort(uint32 offset, uint32 data); + // コントロールポートの読み出し uint32 ReadCtrl() const { return ctrl; } // コントロールポートへの書き込み void WriteCtrl(uint32); // PortC への個別書き込み - virtual void SetPC(int, int); + virtual void SetPC(uint, uint) = 0; + + // 共通部分 + int MonitorScreenCommon(TextScreen& screen, int y); // 7 6 5 4 3 2 1 0 // 1 AM AM AD CHD BM BD CLD @@ -54,94 +70,127 @@ class i8255Device }; -class PPIDevice - : public i8255Device +class PPIDevice : public i8255Device { using inherited = i8255Device; - private: - static const int baseaddr = 0xe9a000; + + static const uint32 baseaddr = 0xe9a000; public: PPIDevice(); ~PPIDevice() override; + bool Init() override; + protected: // BusIO インタフェース static const uint32 NPORT = 4; - uint64 Read(uint32 addr); - uint64 Write(uint32 addr, uint32 data); - uint64 Peek(uint32 addr); + busdata ReadPort(uint32 offset); + busdata WritePort(uint32 offset, uint32 data); + busdata PeekPort(uint32 offset); + + private: + uint32 GetPC() const; + void SetPC(uint, uint) override; + + // ADPCM サンプリングレートの設定値(0..3)をこちらでも持っておく。 + uint32 adpcm_rate {}; + + ADPCMDevice *adpcm {}; }; -class PIO0Device - : public i8255Device +class PIO0Device : public i8255Device { using inherited = i8255Device; + + static const int INT_H = 0; + static const int INT_L = 1; + public: PIO0Device(); ~PIO0Device() override; bool Init() override; + void ResetHard(bool poweron) override; - void MonitorUpdate(TextScreen&) override; + // DIPSW #1-1 が Up なら true を返す (ROM エミュレーション用) + bool IsDIPSW11Up() const { return dipsw1[0]; } - // DIP-SW1 の状態を取得 (ROM エミュレーション用) - // - // b7 b6 b5 b4 b3 b2 b1 b0 - // +------+------+------+------+------+------+------+------+ - // | #1-8 | #1-7 | #1-6 | #1-5 | #1-4 | #1-3 | #1-2 | #1-1 | - // +------+------+------+------+------+------+------+------+ - // %1 が UP、%0 が DOWN - uint32 GetDIPSW1() const { return GetPA(); } + // XP からの割り込みは PIO0 が中継する + void InterruptXPHigh(); + void InterruptXPLow(); protected: // BusIO インタフェース static const uint32 NPORT = 4; - uint64 Read(uint32 addr); - uint64 Write(uint32 addr, uint32 data); - uint64 Peek(uint32 addr); + busdata ReadPort(uint32 offset); + busdata WritePort(uint32 offset, uint32 data); + busdata PeekPort(uint32 offset); private: uint32 GetPA() const; uint32 GetPB() const; uint32 GetPC() const; - void SetPC(int, int) override; + void SetPC(uint, uint) override; + void ChangeInterrupt(); + + DECLARE_MONITOR_SCREEN(MonitorScreen); bool dipsw1[8] {}; bool dipsw2[8] {}; - bool int1rq {}; // $01 INT1 割り込み要求 - bool int1en {}; // $04 INT1 割り込み許可 - bool int5rq {}; // $08 INT5 割り込み要求 - bool int5en {}; // $10 INT5 割り込み許可 + bool msb_first {}; // DIP-SW の1番が MSB なら true (LUNA-88K) + std::array intreq {}; // XP 割り込み要求 + std::array inten {}; // XP 割り込み許可 bool parity {}; // $40 パリティ有効/無効 bool xp_reset {}; // $80 XP リセット + + Monitor *monitor {}; + + InterruptDevice *interrupt {}; + PIO1Device *pio1 {}; }; -class PIO1Device - : public i8255Device +class PIO1Device : public i8255Device { using inherited = i8255Device; public: PIO1Device(); ~PIO1Device() override; - void ResetHard() override; + bool Init() override; + void ResetHard(bool poweron) override; + + // PIO0 の下請け + void MonitorScreenPIO1(TextScreen& screen, int y); - protected: // BusIO インタフェース + // (内蔵 ROM からのアクセス用に特別に public にしてある) + busdata WritePort(uint32 offset, uint32 data); + protected: static const uint32 NPORT = 4; - uint64 Read(uint32 addr); - uint64 Write(uint32 addr, uint32 data); - uint64 Peek(uint32 addr); + busdata ReadPort(uint32 offset); + busdata PeekPort(uint32 offset); private: - void SetPC(int, int) override; - void PowerOffCallback(Event& ev); + uint32 GetPC() const; + void SetPC(uint, uint) override; + + DECLARE_MONITOR_SCREEN(MonitorScreen); bool power {}; // パワーダウン (false で電源オフ指示) bool xp_intreq {}; // XP 割り込み要求。あり(true)なら %0 - Event poffevent {}; // 電源オフイベント + + LCDDevice *lcd {}; + MPU64180Device *mpu64180 {}; + PowerDevice *powerdev {}; }; -extern std::unique_ptr gPIO0; -extern std::unique_ptr gPIO1; +inline PPIDevice *GetPPIDevice() { + return Object::GetObject(OBJ_PPI); +} +inline PIO0Device *GetPIO0Device() { + return Object::GetObject(OBJ_PIO0); +} +inline PIO1Device *GetPIO1Device() { + return Object::GetObject(OBJ_PIO1); +}