diff --git a/Components/68901/MFP68901.cpp b/Components/68901/MFP68901.cpp index 5c83da90d..4ba27e068 100644 --- a/Components/68901/MFP68901.cpp +++ b/Components/68901/MFP68901.cpp @@ -9,7 +9,7 @@ #include "MFP68901.hpp" #define LOG_PREFIX "[MFP] " -#define NDEBUG +//#define NDEBUG #include "../../Outputs/Log.hpp" using namespace Motorola::MFP68901; @@ -17,9 +17,15 @@ using namespace Motorola::MFP68901; uint8_t MFP68901::read(int address) { address &= 0x1f; switch(address) { - case 0x00: LOG("Read: general purpose IO"); break; - case 0x01: LOG("Read: active edge"); break; - case 0x02: LOG("Read: data direction"); break; + case 0x00: + LOG("Read: general purpose IO " << PADHEX(2) << int(gpip_input_ | gpip_direction_)); + return gpip_input_ | gpip_direction_; + case 0x01: + LOG("Read: active edge " << PADHEX(2) << int(gpip_active_edge_)); + return gpip_active_edge_; + case 0x02: + LOG("Read: data direction " << PADHEX(2) << int(gpip_direction_)); + return gpip_direction_; case 0x03: LOG("Read: interrupt enable A"); break; case 0x04: LOG("Read: interrupt enable B"); break; case 0x05: LOG("Read: interrupt pending A"); break; @@ -46,9 +52,20 @@ uint8_t MFP68901::read(int address) { void MFP68901::write(int address, uint8_t value) { address &= 0x1f; switch(address) { - case 0x00: LOG("Write: general purpose IO"); break; - case 0x01: LOG("Write: active edge"); break; - case 0x02: LOG("Write: data direction"); break; + case 0x00: + LOG("Write: general purpose IO " << PADHEX(2) << int(value)); + gpip_output_ = value; + break; + case 0x01: + LOG("Write: active edge " << PADHEX(2) << int(value)); + gpip_active_edge_ = value; + reevaluate_gpip_interrupts(); + break; + case 0x02: + LOG("Write: data direction " << PADHEX(2) << int(value)); + gpip_direction_ = value; + reevaluate_gpip_interrupts(); + break; case 0x03: LOG("Write: interrupt enable A"); break; case 0x04: LOG("Write: interrupt enable B"); break; case 0x05: LOG("Write: interrupt pending A"); break; @@ -173,3 +190,22 @@ void MFP68901::decrement_timer(int timer) { // TODO: interrupt. Reload, possibly. } } + +// MARK: - GPIP +void MFP68901::set_port_input(uint8_t input) { + gpip_input_ = input; + reevaluate_gpip_interrupts(); +} + +uint8_t MFP68901::get_port_output() { + return 0xff; +} + +void MFP68901::reevaluate_gpip_interrupts() { + const uint8_t gpip_state = gpip_input_ ^ gpip_active_edge_; + // An interrupt is detected on any falling edge. + if((gpip_state ^ gpip_interrupt_state_) & gpip_interrupt_state_) { + LOG("Should post GPIP interrupt"); + } + gpip_interrupt_state_ = gpip_state; +} diff --git a/Components/68901/MFP68901.hpp b/Components/68901/MFP68901.hpp index d27839765..f7dcf7978 100644 --- a/Components/68901/MFP68901.hpp +++ b/Components/68901/MFP68901.hpp @@ -17,12 +17,7 @@ namespace MFP68901 { class PortHandler { public: - /*! - Requests the current input on the GPIP port. - */ - virtual uint8_t get_port_input() { - return 0xff; - } + // TODO: announce changes in output. }; class MFP68901 { @@ -59,6 +54,15 @@ class MFP68901 { } timers_[4]; HalfCycles cycles_left_; + + // MARK: - GPIP + uint8_t gpip_input_ = 0; + uint8_t gpip_output_ = 0; + uint8_t gpip_active_edge_ = 0; + uint8_t gpip_direction_ = 0; + uint8_t gpip_interrupt_state_ = 0; + + void reevaluate_gpip_interrupts(); }; } diff --git a/Machines/AtariST/AtariST.cpp b/Machines/AtariST/AtariST.cpp index 8ac2bc970..256005def 100644 --- a/Machines/AtariST/AtariST.cpp +++ b/Machines/AtariST/AtariST.cpp @@ -214,7 +214,8 @@ class ConcreteMachine: public Atari::ST::Machine, public CPU::MC68000::BusHandler, public CRTMachine::Machine, - public ClockingHint::Observer { + public ClockingHint::Observer, + public Motorola::ACIA::ACIA::InterruptDelegate { public: ConcreteMachine(const Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : mc68000_(*this), @@ -250,9 +251,14 @@ class ConcreteMachine: memory_map_[0xff] = BusDevice::IO; + midi_acia_->set_interrupt_delegate(this); + keyboard_acia_->set_interrupt_delegate(this); + midi_acia_->set_clocking_hint_observer(this); keyboard_acia_->set_clocking_hint_observer(this); ikbd_.set_clocking_hint_observer(this); + + set_gpip_input(); } ~ConcreteMachine() { @@ -408,19 +414,6 @@ class ConcreteMachine: mfp_->write(int(address), cycle.value->halves.high); } } - - /* - Atari ST GPIP bits: - - GPIP 7: monochrome monitor detect - GPIP 6: RS-232 ring indicator - GPIP 5: FD/HD interrupt - GPIP 4: keyboard/MIDI interrupt - GPIP 3: unused - GPIP 2: RS-232 clear to send - GPIP 1: RS-232 carrier detect - GPIP 0: centronics busy - */ break; // Video controls. @@ -584,6 +577,7 @@ class ConcreteMachine: }; BusDevice memory_map_[256]; + // MARK: - Clocking Management. bool may_defer_acias_ = true; bool keyboard_needs_clock_ = false; void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final { @@ -594,6 +588,29 @@ class ConcreteMachine: (midi_acia_.last_valid()->preferred_clocking() != ClockingHint::Preference::RealTime); keyboard_needs_clock_ = ikbd_.preferred_clocking() != ClockingHint::Preference::None; } + + // MARK: - GPIP input. + void acia6850_did_change_interrupt_status(Motorola::ACIA::ACIA *acia) final { + set_gpip_input(); + } + void set_gpip_input() { + /* + Atari ST GPIP bits: + + GPIP 7: monochrome monitor detect + GPIP 6: RS-232 ring indicator + GPIP 5: FD/HD interrupt + GPIP 4: keyboard/MIDI interrupt + GPIP 3: unused + GPIP 2: RS-232 clear to send + GPIP 1: RS-232 carrier detect + GPIP 0: centronics busy + */ + mfp_->set_port_input( + 0x80 | + ((keyboard_acia_->get_interrupt_line() || midi_acia_->get_interrupt_line()) ? 0x10 : 0x00) + ); + } }; }