mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 05:29:23 +00:00
Simplify 'get_next_sequence_point' -> 'next_sequence_point'.
This commit is contained in:
parent
211a6e5114
commit
8efb6a9226
@ -26,7 +26,7 @@
|
||||
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
|
||||
separate @c TargetTimeScale at template declaration.
|
||||
|
||||
If the held object implements get_next_sequence_point() then it'll be used to flush implicitly
|
||||
If the held object implements @c next_sequence_point() then it'll be used to flush implicitly
|
||||
as and when sequence points are hit. Callers can use will_flush() to predict these.
|
||||
|
||||
If the held object is a subclass of ClockingHint::Source, this template will register as an
|
||||
@ -40,7 +40,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
private:
|
||||
/*!
|
||||
A std::unique_ptr deleter which causes an update_sequence_point to occur on the actor supplied
|
||||
to it at construction if it implements get_next_sequence_point(). Otherwise destruction is a no-op.
|
||||
to it at construction if it implements @c next_sequence_point(). Otherwise destruction is a no-op.
|
||||
|
||||
**Does not delete the object.**
|
||||
|
||||
@ -247,9 +247,9 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
// going to be applied then do a direct max -> max translation rather than
|
||||
// allowing the arithmetic to overflow.
|
||||
if constexpr (divider == 1 && std::is_same_v<LocalTimeScale, TargetTimeScale>) {
|
||||
time_until_event_ = object_.get_next_sequence_point();
|
||||
time_until_event_ = object_.next_sequence_point();
|
||||
} else {
|
||||
const auto time = object_.get_next_sequence_point();
|
||||
const auto time = object_.next_sequence_point();
|
||||
if(time == TargetTimeScale::max()) {
|
||||
time_until_event_ = LocalTimeScale::max();
|
||||
} else {
|
||||
@ -272,7 +272,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
bool did_flush_ = false;
|
||||
|
||||
template <typename S, typename = void> struct has_sequence_points : std::false_type {};
|
||||
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().get_next_sequence_point()))> : std::true_type {};
|
||||
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().next_sequence_point()))> : std::true_type {};
|
||||
|
||||
ClockingHint::Preference clocking_preference_ = ClockingHint::Preference::JustInTime;
|
||||
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference clocking) {
|
||||
|
@ -207,7 +207,7 @@ void MFP68901::run_for(HalfCycles time) {
|
||||
}
|
||||
}
|
||||
|
||||
HalfCycles MFP68901::get_next_sequence_point() {
|
||||
HalfCycles MFP68901::next_sequence_point() {
|
||||
return HalfCycles::max();
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class MFP68901: public ClockingHint::Source {
|
||||
/// so that mechanism can also be used to reduce the quantity of calls into this class.
|
||||
///
|
||||
/// @discussion TODO, alas.
|
||||
HalfCycles get_next_sequence_point();
|
||||
HalfCycles next_sequence_point();
|
||||
|
||||
/// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms.
|
||||
void set_timer_event_input(int channel, bool value);
|
||||
|
@ -108,7 +108,7 @@ template <Personality personality> class TMS9918: private Base<personality> {
|
||||
If get_interrupt_line is true now of if get_interrupt_line would
|
||||
never return true, returns HalfCycles::max().
|
||||
*/
|
||||
HalfCycles get_next_sequence_point() const;
|
||||
HalfCycles next_sequence_point() const;
|
||||
|
||||
/*!
|
||||
Returns the amount of time until the nominated line interrupt position is
|
||||
|
@ -1268,7 +1268,7 @@ uint8_t TMS9918<personality>::get_current_line() const {
|
||||
return uint8_t(source_row);
|
||||
}
|
||||
template <Personality personality>
|
||||
HalfCycles TMS9918<personality>::get_next_sequence_point() const {
|
||||
HalfCycles TMS9918<personality>::next_sequence_point() const {
|
||||
if(!this->generate_interrupts_ && !this->enable_line_interrupts_) return HalfCycles::max();
|
||||
if(get_interrupt_line()) return HalfCycles::max();
|
||||
|
||||
|
@ -1171,7 +1171,7 @@ class ConcreteMachine:
|
||||
machine_->update_audio();
|
||||
}
|
||||
~AudioUpdater() {
|
||||
machine_->cycles_until_audio_event_ = machine_->sound_glu_.get_next_sequence_point();
|
||||
machine_->cycles_until_audio_event_ = machine_->sound_glu_.next_sequence_point();
|
||||
}
|
||||
private:
|
||||
ConcreteMachine *machine_;
|
||||
|
@ -218,7 +218,7 @@ uint8_t GLU::get_address_high() {
|
||||
|
||||
// MARK: - Update logic.
|
||||
|
||||
Cycles GLU::get_next_sequence_point() const {
|
||||
Cycles GLU::next_sequence_point() const {
|
||||
uint32_t result = std::numeric_limits<decltype(result)>::max();
|
||||
|
||||
for(int c = 0; c < local_.oscillator_count; c++) {
|
||||
|
@ -31,7 +31,7 @@ class GLU: public Outputs::Speaker::SampleSource {
|
||||
uint8_t get_address_high();
|
||||
|
||||
void run_for(Cycles);
|
||||
Cycles get_next_sequence_point() const;
|
||||
Cycles next_sequence_point() const;
|
||||
bool get_interrupt_line();
|
||||
|
||||
// SampleSource.
|
||||
|
@ -191,7 +191,7 @@ void Video::advance(Cycles cycles) {
|
||||
}
|
||||
}
|
||||
|
||||
Cycles Video::get_next_sequence_point() const {
|
||||
Cycles Video::next_sequence_point() const {
|
||||
const int cycles_into_row = cycles_into_frame_ % CyclesPerLine;
|
||||
const int row = cycles_into_frame_ / CyclesPerLine;
|
||||
|
||||
|
@ -60,7 +60,7 @@ class Video: public Apple::II::VideoSwitches<Cycles> {
|
||||
Outputs::Display::DisplayType get_display_type() const;
|
||||
|
||||
/// Determines the period until video might autonomously update its interrupt lines.
|
||||
Cycles get_next_sequence_point() const;
|
||||
Cycles next_sequence_point() const;
|
||||
|
||||
/// Sets the Mega II interrupt enable state — 1/4-second and VBL interrupts are
|
||||
/// generated here.
|
||||
|
@ -575,7 +575,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
|
||||
video_.run_for(time_until_video_event_);
|
||||
time_since_video_update_ -= time_until_video_event_;
|
||||
time_until_video_event_ = video_.get_next_sequence_point();
|
||||
time_until_video_event_ = video_.next_sequence_point();
|
||||
|
||||
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
|
||||
}
|
||||
@ -626,7 +626,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
|
||||
forceinline void update_video() {
|
||||
video_.run_for(time_since_video_update_.flush<HalfCycles>());
|
||||
time_until_video_event_ = video_.get_next_sequence_point();
|
||||
time_until_video_event_ = video_.next_sequence_point();
|
||||
}
|
||||
|
||||
Inputs::Mouse &get_mouse() final {
|
||||
|
@ -170,7 +170,7 @@ bool Video::vsync() {
|
||||
return line >= 353 && line < 356;
|
||||
}
|
||||
|
||||
HalfCycles Video::get_next_sequence_point() {
|
||||
HalfCycles Video::next_sequence_point() {
|
||||
const auto line = (frame_position_ / line_length).as_integral();
|
||||
if(line >= 353 && line < 356) {
|
||||
// Currently in vsync, so get time until start of line 357,
|
||||
|
@ -80,7 +80,7 @@ class Video {
|
||||
@returns the amount of time until there is next a transition on the
|
||||
vsync signal.
|
||||
*/
|
||||
HalfCycles get_next_sequence_point();
|
||||
HalfCycles next_sequence_point();
|
||||
|
||||
private:
|
||||
DeferredAudio &audio_;
|
||||
|
@ -395,7 +395,7 @@ bool Video::display_enabled() {
|
||||
return public_state_.display_enable;
|
||||
}
|
||||
|
||||
HalfCycles Video::get_next_sequence_point() {
|
||||
HalfCycles Video::next_sequence_point() {
|
||||
// The next sequence point will be whenever display_enabled, vsync or hsync next changes.
|
||||
|
||||
// Sequence of events within a standard line:
|
||||
|
@ -68,7 +68,7 @@ class Video {
|
||||
@returns the number of cycles until there is next a change in the hsync,
|
||||
vsync or display_enable outputs.
|
||||
*/
|
||||
HalfCycles get_next_sequence_point();
|
||||
HalfCycles next_sequence_point();
|
||||
|
||||
/*!
|
||||
@returns @c true if the horizontal sync output is currently active; @c false otherwise.
|
||||
|
@ -370,7 +370,7 @@ void VideoOutput::setup_base_address() {
|
||||
|
||||
// MARK: - Interrupts
|
||||
|
||||
Cycles VideoOutput::get_next_sequence_point() {
|
||||
Cycles VideoOutput::next_sequence_point() {
|
||||
if(output_position_ < real_time_clock_interrupt_1) {
|
||||
return real_time_clock_interrupt_1 - output_position_;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class VideoOutput {
|
||||
|
||||
This result may be mutated by calls to @c write.
|
||||
*/
|
||||
Cycles get_next_sequence_point();
|
||||
Cycles next_sequence_point();
|
||||
|
||||
/*!
|
||||
@returns a bit mask of all interrupts that have been triggered since the last call to get_interrupt().
|
||||
|
@ -315,7 +315,7 @@ void TimedInterruptSource::run_for(Cycles duration) {
|
||||
update_channel(1, rate_ == InterruptRate::ToneGenerator1, cycles.as<int>());
|
||||
}
|
||||
|
||||
Cycles TimedInterruptSource::get_next_sequence_point() const {
|
||||
Cycles TimedInterruptSource::next_sequence_point() const {
|
||||
// Since both the 1kHz and 50Hz timers are integer dividers of the 1Hz timer, there's no need
|
||||
// to factor that one in when determining the next sequence point for either of those.
|
||||
switch(rate_) {
|
||||
|
@ -144,7 +144,7 @@ class TimedInterruptSource {
|
||||
|
||||
/// @returns The amount of time from now until the earliest that
|
||||
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
||||
Cycles get_next_sequence_point() const;
|
||||
Cycles next_sequence_point() const;
|
||||
|
||||
private:
|
||||
static constexpr Cycles clock_rate{250000};
|
||||
|
@ -467,7 +467,7 @@ void Nick::set_output_type(OutputType type, bool force_flush) {
|
||||
|
||||
// MARK: - Sequence points.
|
||||
|
||||
Cycles Nick::get_next_sequence_point() const {
|
||||
Cycles Nick::next_sequence_point() const {
|
||||
constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
||||
// interrupt line may change. That is, after the
|
||||
// second byte of the mode line has been read.
|
||||
|
@ -38,7 +38,7 @@ class Nick {
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||
|
||||
/// @returns The amount of time until the next potential change in interrupt output.
|
||||
Cycles get_next_sequence_point() const;
|
||||
Cycles next_sequence_point() const;
|
||||
|
||||
/*!
|
||||
@returns The current state of the interrupt line — @c true for active;
|
||||
|
@ -315,7 +315,7 @@ template <Timing timing> class Video {
|
||||
/*!
|
||||
@returns The amount of time until the next change in the interrupt line, that being the only internally-observeable output.
|
||||
*/
|
||||
HalfCycles get_next_sequence_point() {
|
||||
HalfCycles next_sequence_point() {
|
||||
constexpr auto timings = get_timings();
|
||||
|
||||
// Is the frame still ahead of this interrupt?
|
||||
|
@ -124,7 +124,7 @@ struct VideoTester {
|
||||
display_enable = _video->display_enabled();
|
||||
vsync = _video->vsync();
|
||||
hsync = _video->hsync();
|
||||
next_event = _video->get_next_sequence_point();
|
||||
next_event = _video->next_sequence_point();
|
||||
} else {
|
||||
NSAssert(display_enable == _video->display_enabled(), @"Unannounced change in display enabled at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
||||
NSAssert(vsync == _video->vsync(), @"Unannounced change in vsync at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
||||
|
@ -38,7 +38,7 @@
|
||||
int toggles = 0;
|
||||
int interrupts = 0;
|
||||
uint8_t dividerState = _interruptSource->get_divider_state() & 1;
|
||||
int nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
||||
int nextSequencePoint = _interruptSource->next_sequence_point().as<int>();
|
||||
|
||||
for(int c = 0; c < 250000 * 5; c++) {
|
||||
// Advance one cycle. Clock is 500,000 Hz.
|
||||
@ -55,7 +55,7 @@
|
||||
const uint8_t newInterrupts = _interruptSource->get_new_interrupts();
|
||||
if(newInterrupts) {
|
||||
XCTAssertEqual(nextSequencePoint, 0);
|
||||
nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
||||
nextSequencePoint = _interruptSource->next_sequence_point().as<int>();
|
||||
|
||||
if(newInterrupts & 0x02) {
|
||||
++interrupts;
|
||||
@ -66,7 +66,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssertEqual(nextSequencePoint, _interruptSource->get_next_sequence_point().as<int>(), @"At cycle %d", c);
|
||||
XCTAssertEqual(nextSequencePoint, _interruptSource->next_sequence_point().as<int>(), @"At cycle %d", c);
|
||||
}
|
||||
|
||||
XCTAssertEqual(toggles, int(expectedInterruptsPerSecond * 5.0));
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
- (void)testInterruptPrediction {
|
||||
// Run for the number of cycles implied by the number of lines.
|
||||
int next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
int next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||
bool last_interrupt_line = _nick->get_interrupt_line();
|
||||
|
||||
for(int c = 0; c < _totalLines*912; c++) {
|
||||
@ -61,9 +61,9 @@
|
||||
last_interrupt_line = interrupt_line;
|
||||
|
||||
if(!next_sequence_point) {
|
||||
next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||
} else {
|
||||
const int expected_next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
const int expected_next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||
XCTAssertEqual(next_sequence_point, expected_next_sequence_point);
|
||||
}
|
||||
}
|
||||
|
@ -31,14 +31,14 @@
|
||||
int c = 5;
|
||||
bool vsync = _video->vsync();
|
||||
while(c--) {
|
||||
auto remaining_time_in_state = _video->get_next_sequence_point().as_integral();
|
||||
auto remaining_time_in_state = _video->next_sequence_point().as_integral();
|
||||
NSLog(@"Vsync %@ expected for %@ half-cycles", vsync ? @"on" : @"off", @(remaining_time_in_state));
|
||||
while(remaining_time_in_state--) {
|
||||
XCTAssertEqual(vsync, _video->vsync());
|
||||
_video->run_for(HalfCycles(1));
|
||||
|
||||
if(remaining_time_in_state)
|
||||
XCTAssertEqual(remaining_time_in_state, _video->get_next_sequence_point().as_integral());
|
||||
XCTAssertEqual(remaining_time_in_state, _video->next_sequence_point().as_integral());
|
||||
}
|
||||
vsync ^= true;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
||||
vdp.write(1, 0x8a);
|
||||
|
||||
// Get time until interrupt.
|
||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
||||
auto time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||
|
||||
// Check that an interrupt is now scheduled.
|
||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
||||
@ -55,7 +55,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
||||
NSAssert(!vdp.get_interrupt_line(), @"Interrupt wasn't reset by status read");
|
||||
|
||||
// Check interrupt flag isn't set prior to the reported time.
|
||||
time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
||||
time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||
vdp.run_for(HalfCycles(time_until_interrupt));
|
||||
NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early [2]");
|
||||
|
||||
@ -82,7 +82,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
||||
|
||||
// Clear the pending interrupt and ask about the next one (i.e. the first one).
|
||||
vdp.read(1);
|
||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
||||
auto time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||
|
||||
// Check that an interrupt is now scheduled.
|
||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
||||
@ -116,7 +116,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
||||
|
||||
// Now run through an entire frame...
|
||||
int half_cycles = 262*228*2;
|
||||
auto last_time_until_interrupt = vdp.get_next_sequence_point().as_integral();
|
||||
auto last_time_until_interrupt = vdp.next_sequence_point().as_integral();
|
||||
while(half_cycles--) {
|
||||
// Validate that an interrupt happened if one was expected, and clear anything that's present.
|
||||
NSAssert(vdp.get_interrupt_line() == (last_time_until_interrupt == HalfCycles::max().as_integral()), @"Unexpected interrupt state change; expected %d but got %d; position %d %d @ %d", (last_time_until_interrupt == 0), vdp.get_interrupt_line(), c, with_eof, half_cycles);
|
||||
@ -129,7 +129,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
||||
vdp.run_for(HalfCycles(1));
|
||||
|
||||
// Get the time until interrupt.
|
||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral();
|
||||
auto time_until_interrupt = vdp.next_sequence_point().as_integral();
|
||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() || vdp.get_interrupt_line(), @"No interrupt scheduled; position %d %d @ %d", c, with_eof, half_cycles);
|
||||
NSAssert(time_until_interrupt >= 0, @"Interrupt is scheduled in the past; position %d %d @ %d", c, with_eof, half_cycles);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user