From eb157f15f317dc45310f8ee53d8b83af0e8e810d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 9 Oct 2021 04:08:59 -0700 Subject: [PATCH] Adds index hole interrupt. --- Components/6526/6526.hpp | 3 + .../Implementation/6526Implementation.hpp | 8 ++ .../6526/Implementation/6526Storage.hpp | 1 + Machines/Amiga/Chipset.cpp | 17 ++-- Machines/Amiga/Chipset.hpp | 85 ++++++++++--------- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/Components/6526/6526.hpp b/Components/6526/6526.hpp index 3af90d700..4845368d7 100644 --- a/Components/6526/6526.hpp +++ b/Components/6526/6526.hpp @@ -63,6 +63,9 @@ template class MOS6526: /// Sets the current state of the CNT input. void set_cnt_input(bool active); + /// Sets the current state of the FLG input. + void set_flag_input(bool low); + private: PortHandlerT &port_handler_; TODStorage tod_; diff --git a/Components/6526/Implementation/6526Implementation.hpp b/Components/6526/Implementation/6526Implementation.hpp index 46eb3ef81..aedae76f6 100644 --- a/Components/6526/Implementation/6526Implementation.hpp +++ b/Components/6526/Implementation/6526Implementation.hpp @@ -54,6 +54,14 @@ void MOS6526::set_cnt_input(bool active) { cnt_state_ = active; } +template +void MOS6526::set_flag_input(bool low) { + if(low && !flag_state_) { + posit_interrupt(0x10); + } + flag_state_ = low; +} + template void MOS6526::write(int address, uint8_t value) { address &= 0xf; diff --git a/Components/6526/Implementation/6526Storage.hpp b/Components/6526/Implementation/6526Storage.hpp index 55e406401..9b4c36a83 100644 --- a/Components/6526/Implementation/6526Storage.hpp +++ b/Components/6526/Implementation/6526Storage.hpp @@ -178,6 +178,7 @@ template <> class TODStorage: public TODBase { struct MOS6526Storage { bool cnt_state_ = false; // Inactive by default. bool cnt_edge_ = false; + bool flag_state_ = false; HalfCycles half_divider_; uint8_t output_[2] = {0, 0}; diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index b2a38f538..c0d6573e4 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -37,13 +37,13 @@ Chipset::Chipset(MemoryMap &map, int input_clock_rate) : blitter_(*this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1), bitplanes_(*this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1), copper_(*this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1), - disk_(*this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1), - disk_controller_(Cycles(input_clock_rate), disk_), crt_(908, 4, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4), cia_a_handler_(map, disk_controller_), cia_b_handler_(disk_controller_), cia_a(cia_a_handler_), - cia_b(cia_b_handler_) { + cia_b(cia_b_handler_), + disk_(*this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1), + disk_controller_(Cycles(input_clock_rate), disk_, cia_b) { disk_controller_.set_clocking_hint_observer(this); } @@ -1052,9 +1052,10 @@ void Chipset::set_component_prefers_clocking(ClockingHint::Source *, ClockingHin // MARK: - Disk Controller. -Chipset::DiskController::DiskController(Cycles clock_rate, DiskDMA &disk_dma) : +Chipset::DiskController::DiskController(Cycles clock_rate, DiskDMA &disk_dma, CIAB &cia) : Storage::Disk::Controller(clock_rate), - disk_dma_(disk_dma) { + disk_dma_(disk_dma), + cia_(cia) { // Add four drives. for(int c = 0; c < 4; c++) { @@ -1097,7 +1098,11 @@ void Chipset::DiskController::set_control(uint16_t control) { } void Chipset::DiskController::process_index_hole() { - // TODO: should connect to CIA B's flag input. + // Pulse the CIA flag input. + // + // TODO: rectify once drives do an actual index pulse, with length. + cia_.set_flag_input(true); + cia_.set_flag_input(false); } void Chipset::DiskController::set_mtr_sel_side_dir_step(uint8_t value) { diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 43a3e40ef..2ee3e06bc 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -223,6 +223,50 @@ class Chipset: private ClockingHint::Observer { uint16_t status; } serial_; + // MARK: - Pixel output. + + Outputs::CRT::CRT crt_; + uint16_t palette_[32]{}; + uint16_t swizzled_palette_[32]{}; + + // MARK: - CIAs + private: + class DiskController; + + class CIAAHandler: public MOS::MOS6526::PortHandler { + public: + CIAAHandler(MemoryMap &map, DiskController &controller); + void set_port_output(MOS::MOS6526::Port port, uint8_t value); + uint8_t get_port_input(MOS::MOS6526::Port port); + void set_activity_observer(Activity::Observer *observer); + + private: + MemoryMap &map_; + DiskController &controller_; + Activity::Observer *observer_ = nullptr; + inline static const std::string led_name = "Power"; + } cia_a_handler_; + + class CIABHandler: public MOS::MOS6526::PortHandler { + public: + CIABHandler(DiskController &controller); + void set_port_output(MOS::MOS6526::Port port, uint8_t value); + uint8_t get_port_input(MOS::MOS6526::Port); + + private: + DiskController &controller_; + } cia_b_handler_; + + public: + using CIAA = MOS::MOS6526::MOS6526; + using CIAB = MOS::MOS6526::MOS6526; + + // CIAs are provided for direct access; it's up to the caller properly + // to distinguish relevant accesses. + CIAA cia_a; + CIAB cia_b; + + private: // MARK: - Disk drives. class DiskDMA: public DMADevice<1> { @@ -245,7 +289,7 @@ class Chipset: private ClockingHint::Observer { class DiskController: public Storage::Disk::Controller { public: - DiskController(Cycles clock_rate, DiskDMA &disk_dma); + DiskController(Cycles clock_rate, DiskDMA &disk_dma, CIAB &cia); void set_mtr_sel_side_dir_step(uint8_t); uint8_t get_rdy_trk0_wpro_chng(); @@ -275,50 +319,13 @@ class Chipset: private ClockingHint::Observer { bool sync_with_word_ = false; DiskDMA &disk_dma_; + CIAB &cia_; } disk_controller_; void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final; bool disk_controller_is_sleeping_ = false; uint16_t paula_disk_control_ = 0; - - // MARK: - Pixel output. - - Outputs::CRT::CRT crt_; - uint16_t palette_[32]{}; - uint16_t swizzled_palette_[32]{}; - - // MARK: - CIAs - private: - class CIAAHandler: public MOS::MOS6526::PortHandler { - public: - CIAAHandler(MemoryMap &map, DiskController &controller); - void set_port_output(MOS::MOS6526::Port port, uint8_t value); - uint8_t get_port_input(MOS::MOS6526::Port port); - void set_activity_observer(Activity::Observer *observer); - - private: - MemoryMap &map_; - DiskController &controller_; - Activity::Observer *observer_ = nullptr; - inline static const std::string led_name = "Power"; - } cia_a_handler_; - - class CIABHandler: public MOS::MOS6526::PortHandler { - public: - CIABHandler(DiskController &controller); - void set_port_output(MOS::MOS6526::Port port, uint8_t value); - uint8_t get_port_input(MOS::MOS6526::Port); - - private: - DiskController &controller_; - } cia_b_handler_; - - public: - // CIAs are provided for direct access; it's up to the caller properly - // to distinguish relevant accesses. - MOS::MOS6526::MOS6526 cia_a; - MOS::MOS6526::MOS6526 cia_b; }; }