1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 18:55:48 +00:00

Moves interrupt level selection outside the loop.

This commit is contained in:
Thomas Harte 2019-07-23 23:13:03 -04:00
parent 4aca6c5ef8
commit 0469f0240b
3 changed files with 49 additions and 11 deletions

View File

@ -64,6 +64,7 @@ std::uint8_t z8530::read(int address) {
}
pointer_ = 0;
update_delegate();
return result;
}
@ -110,10 +111,12 @@ void z8530::write(int address, std::uint8_t value) {
}
}
}
update_delegate();
}
void z8530::set_dcd(int port, bool level) {
channels_[port].set_dcd(level);
update_delegate();
}
// MARK: - Channel implementations
@ -255,3 +258,11 @@ bool z8530::Channel::get_interrupt_line() {
(interrupt_mask_ & 1) && external_status_interrupt_;
// TODO: other potential causes of an interrupt.
}
void z8530::update_delegate() {
const bool interrupt_line = get_interrupt_line();
if(interrupt_line != previous_interrupt_line_) {
previous_interrupt_line_ = interrupt_line;
if(delegate_) delegate_->did_change_interrupt_status(this, interrupt_line);
}
}

View File

@ -35,6 +35,13 @@ class z8530 {
void reset();
bool get_interrupt_line();
struct Delegate {
virtual void did_change_interrupt_status(z8530 *, bool new_status) = 0;
};
void set_delegate(Delegate *delegate) {
delegate_ = delegate;
}
/*
**Interface for serial port input.**
*/
@ -79,6 +86,10 @@ class z8530 {
uint8_t interrupt_vector_ = 0;
uint8_t master_interrupt_control_ = 0;
bool previous_interrupt_line_ = false;
void update_delegate();
Delegate *delegate_ = nullptr;
};
}

View File

@ -51,7 +51,8 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
public MediaTarget::Machine,
public MouseMachine::Machine,
public CPU::MC68000::BusHandler,
public KeyboardMachine::MappedMachine {
public KeyboardMachine::MappedMachine,
public Zilog::SCC::z8530::Delegate {
public:
using Target = Analyser::Static::Macintosh::Target;
@ -112,6 +113,9 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
iwm_.iwm.set_drive(0, &drives_[0]);
iwm_.iwm.set_drive(1, &drives_[1]);
// Make sure interrupt changes from the SCC are observed.
scc_.set_delegate(this);
// The Mac runs at 7.8336mHz.
set_clock_rate(double(CLOCK_RATE));
audio_.speaker.set_input_rate(float(CLOCK_RATE) / 2.0f);
@ -208,16 +212,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, false);
}
// Update interrupt input. TODO: move this into a VIA/etc delegate callback?
// Double TODO: does this really cascade like this?
if(scc_.get_interrupt_line()) {
mc68000_.set_interrupt_level(2);
} else if(via_.get_interrupt_line()) {
mc68000_.set_interrupt_level(1);
} else {
mc68000_.set_interrupt_level(0);
}
// A null cycle leaves nothing else to do.
if(!(cycle.operation & (Microcycle::NewAddress | Microcycle::SameAddress))) return delay;
@ -433,6 +427,24 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// TODO: clear all keys.
// MARK: Interrupt updates.
void did_change_interrupt_status(Zilog::SCC::z8530 *sender, bool new_status) override {
update_interrupt_input();
}
void update_interrupt_input() {
// Update interrupt input.
// TODO: does this really cascade like this?
if(scc_.get_interrupt_line()) {
mc68000_.set_interrupt_level(2);
} else if(via_.get_interrupt_line()) {
mc68000_.set_interrupt_level(1);
} else {
mc68000_.set_interrupt_level(0);
}
}
private:
void update_video() {
video_.run_for(time_since_video_update_.flush());
@ -554,6 +566,10 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
audio_.flush();
}
void set_interrupt_status(bool status) {
machine_.update_interrupt_input();
}
private:
ConcreteMachine &machine_;
RealTimeClock &clock_;