mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-21 21:33:54 +00:00
JustInTimeActors can now specify a clock divider.
This commit is contained in:
parent
a7ed357569
commit
c4ef33b23f
@ -139,10 +139,10 @@ template <class T> class WrappedInt {
|
||||
Severs from @c this the effect of dividing by @c divisor; @c this will end up with
|
||||
the value of @c this modulo @c divisor and @c divided by @c divisor is returned.
|
||||
*/
|
||||
forceinline T divide(const T &divisor) {
|
||||
T result(length_ / divisor.length_);
|
||||
length_ %= divisor.length_;
|
||||
return result;
|
||||
template <typename Result = T> forceinline Result divide(const T &divisor) {
|
||||
Result r;
|
||||
static_cast<T *>(this)->fill(r, divisor);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -177,6 +177,11 @@ class Cycles: public WrappedInt<Cycles> {
|
||||
result.length_ = length_;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void fill(Cycles &result, const Cycles &divisor) {
|
||||
result.length_ = length_ / divisor.length_;
|
||||
length_ %= divisor.length_;
|
||||
}
|
||||
};
|
||||
|
||||
/// Describes an integer number of half cycles: single clock signal transitions.
|
||||
@ -215,6 +220,16 @@ class HalfCycles: public WrappedInt<HalfCycles> {
|
||||
result.length_ = length_;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void fill(Cycles &result, const HalfCycles &divisor) {
|
||||
result = Cycles(length_ / (divisor.length_ << 1));
|
||||
length_ %= (divisor.length_ << 1);
|
||||
}
|
||||
|
||||
void fill(HalfCycles &result, const HalfCycles &divisor) {
|
||||
result.length_ = length_ / divisor.length_;
|
||||
length_ %= divisor.length_;
|
||||
}
|
||||
};
|
||||
|
||||
// Create a specialisation of WrappedInt::flush for converting HalfCycles to Cycles
|
||||
|
@ -21,7 +21,7 @@
|
||||
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
|
||||
separate @c TargetTimeScale at template declaration.
|
||||
*/
|
||||
template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale> class JustInTimeActor {
|
||||
template <class T, int divider = 1, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale> class JustInTimeActor {
|
||||
public:
|
||||
/// Constructs a new JustInTimeActor using the same construction arguments as the included object.
|
||||
template<typename... Args> JustInTimeActor(Args&&... args) : object_(std::forward<Args>(args)...) {}
|
||||
@ -44,8 +44,14 @@ template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = Lo
|
||||
}
|
||||
|
||||
/// Flushes all accumulated time.
|
||||
inline void flush() {
|
||||
if(!is_flushed_) object_.run_for(time_since_update_.template flush<TargetTimeScale>());
|
||||
void flush() {
|
||||
if(!is_flushed_) {
|
||||
if(divider == 1) {
|
||||
object_.run_for(time_since_update_.template flush<TargetTimeScale>());
|
||||
} else {
|
||||
object_.run_for(time_since_update_.template divide<TargetTimeScale>(LocalTimeScale(divider)));
|
||||
}
|
||||
}
|
||||
is_flushed_ = true;
|
||||
}
|
||||
|
||||
|
@ -89,18 +89,20 @@ void ACIA::run_for(HalfCycles length) {
|
||||
const int transmit_advance = length.as_int();
|
||||
const auto write_data_time_remaining = transmit.write_data_time_remaining();
|
||||
|
||||
if(transmit_advance > write_data_time_remaining) {
|
||||
if(next_transmission_ != NoTransmission) {
|
||||
transmit.flush_writing();
|
||||
consider_transmission();
|
||||
transmit.advance_writer(transmit_advance - write_data_time_remaining);
|
||||
if(write_data_time_remaining) {
|
||||
if(transmit_advance > write_data_time_remaining) {
|
||||
if(next_transmission_ != NoTransmission) {
|
||||
transmit.flush_writing();
|
||||
consider_transmission();
|
||||
transmit.advance_writer(transmit_advance - write_data_time_remaining);
|
||||
} else {
|
||||
transmit.advance_writer(transmit_advance);
|
||||
update_clocking_observer();
|
||||
interrupt_request_ |= transmit_interrupt_enabled_;
|
||||
}
|
||||
} else {
|
||||
transmit.advance_writer(transmit_advance);
|
||||
update_clocking_observer();
|
||||
interrupt_request_ |= transmit_interrupt_enabled_;
|
||||
}
|
||||
} else {
|
||||
transmit.advance_writer(transmit_advance);
|
||||
}
|
||||
|
||||
// Reception.
|
||||
|
@ -656,9 +656,11 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
return mouse_;
|
||||
}
|
||||
|
||||
using IWMActor = JustInTimeActor<IWM, 1, HalfCycles, Cycles>;
|
||||
|
||||
class VIAPortHandler: public MOS::MOS6522::PortHandler {
|
||||
public:
|
||||
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, JustInTimeActor<IWM, HalfCycles, Cycles> &iwm, Inputs::QuadratureMouse &mouse) :
|
||||
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, IWMActor &iwm, Inputs::QuadratureMouse &mouse) :
|
||||
machine_(machine), clock_(clock), keyboard_(keyboard), audio_(audio), iwm_(iwm), mouse_(mouse) {}
|
||||
|
||||
using Port = MOS::MOS6522::Port;
|
||||
@ -764,14 +766,14 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
RealTimeClock &clock_;
|
||||
Keyboard &keyboard_;
|
||||
DeferredAudio &audio_;
|
||||
JustInTimeActor<IWM, HalfCycles, Cycles> &iwm_;
|
||||
IWMActor &iwm_;
|
||||
Inputs::QuadratureMouse &mouse_;
|
||||
};
|
||||
|
||||
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
|
||||
|
||||
DriveSpeedAccumulator drive_speed_accumulator_;
|
||||
JustInTimeActor<IWM, HalfCycles, Cycles> iwm_;
|
||||
IWMActor iwm_;
|
||||
|
||||
DeferredAudio audio_;
|
||||
Video video_;
|
||||
|
@ -347,6 +347,8 @@ class ConcreteMachine:
|
||||
forceinline void advance_time(HalfCycles length) {
|
||||
cycles_since_audio_update_ += length;
|
||||
mfp_ += length;
|
||||
keyboard_acia_ += length;
|
||||
midi_acia_ += length;
|
||||
|
||||
while(length >= cycles_until_video_event_) {
|
||||
length -= cycles_until_video_event_;
|
||||
@ -366,12 +368,12 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
|
||||
JustInTimeActor<Video, HalfCycles> video_;
|
||||
JustInTimeActor<Video> video_;
|
||||
HalfCycles cycles_until_video_event_;
|
||||
|
||||
JustInTimeActor<Motorola::MFP68901::MFP68901, HalfCycles> mfp_;
|
||||
JustInTimeActor<Motorola::ACIA::ACIA, HalfCycles> keyboard_acia_;
|
||||
JustInTimeActor<Motorola::ACIA::ACIA, HalfCycles> midi_acia_;
|
||||
JustInTimeActor<Motorola::MFP68901::MFP68901> mfp_;
|
||||
JustInTimeActor<Motorola::ACIA::ACIA, 10> keyboard_acia_;
|
||||
JustInTimeActor<Motorola::ACIA::ACIA, 10> midi_acia_;
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||
GI::AY38910::AY38910 ay_;
|
||||
|
@ -397,7 +397,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_;
|
||||
JustInTimeActor<TI::TMS::TMS9918, 1, HalfCycles> vdp_;
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||
TI::SN76489 sn76489_;
|
||||
|
@ -752,7 +752,7 @@ class ConcreteMachine:
|
||||
};
|
||||
|
||||
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_;
|
||||
JustInTimeActor<TI::TMS::TMS9918> vdp_;
|
||||
Intel::i8255::i8255<i8255PortHandler> i8255_;
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||
|
@ -414,7 +414,7 @@ class ConcreteMachine:
|
||||
Target::Region region_;
|
||||
Target::PagingScheme paging_scheme_;
|
||||
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||
JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_;
|
||||
JustInTimeActor<TI::TMS::TMS9918> vdp_;
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||
TI::SN76489 sn76489_;
|
||||
|
Loading…
Reference in New Issue
Block a user