mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Enhances ScanTarget to provide additional timing information.
This commit is contained in:
parent
46d756d298
commit
e9d9ff0da0
@ -68,7 +68,7 @@
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
@ -159,6 +159,18 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested,
|
||||
return horizontal_flywheel_->get_next_event_in_period(hsync_is_requested, cycles_to_run_for, cycles_advanced);
|
||||
}
|
||||
|
||||
Outputs::Display::ScanTarget::Scan::EndPoint CRT::end_point(uint16_t data_offset) {
|
||||
Display::ScanTarget::Scan::EndPoint end_point;
|
||||
|
||||
end_point.x = uint16_t(horizontal_flywheel_->get_current_output_position());
|
||||
end_point.y = uint16_t(vertical_flywheel_->get_current_output_position() / vertical_flywheel_output_divider_);
|
||||
end_point.composite_angle = int16_t((phase_numerator_ << 6) / phase_denominator_) * (is_alernate_line_ ? -1 : 1);
|
||||
end_point.data_offset = data_offset;
|
||||
end_point.cycles_since_end_of_horizontal_retrace = uint16_t(cycles_since_horizontal_sync_ / time_multiplier_);
|
||||
|
||||
return end_point;
|
||||
}
|
||||
|
||||
void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, bool vsync_requested, const Scan::Type type, int number_of_samples) {
|
||||
number_of_cycles *= time_multiplier_;
|
||||
|
||||
@ -186,16 +198,14 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, bool vsync_
|
||||
|
||||
// If outputting, store the start location and scan constants.
|
||||
if(next_scan) {
|
||||
next_scan->end_points[0].x = uint16_t(horizontal_flywheel_->get_current_output_position());
|
||||
next_scan->end_points[0].y = uint16_t(vertical_flywheel_->get_current_output_position() / vertical_flywheel_output_divider_);
|
||||
next_scan->end_points[0].composite_angle = int16_t((phase_numerator_ << 6) / phase_denominator_) * (is_alernate_line_ ? -1 : 1);
|
||||
next_scan->end_points[0].data_offset = uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles);
|
||||
next_scan->end_points[0] = end_point(uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles));
|
||||
next_scan->composite_amplitude = colour_burst_amplitude_;
|
||||
}
|
||||
|
||||
// Advance time: that'll affect both the colour subcarrier position and the number of cycles left to run.
|
||||
phase_numerator_ += next_run_length * colour_cycle_numerator_;
|
||||
number_of_cycles -= next_run_length;
|
||||
cycles_since_horizontal_sync_ += next_run_length;
|
||||
|
||||
// React to the incoming event.
|
||||
horizontal_flywheel_->apply_event(next_run_length, (next_run_length == time_until_horizontal_sync_event) ? next_horizontal_sync_event : Flywheel::SyncEvent::None);
|
||||
@ -203,10 +213,7 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, bool vsync_
|
||||
|
||||
// End the scan if necessary.
|
||||
if(next_scan) {
|
||||
next_scan->end_points[1].x = uint16_t(horizontal_flywheel_->get_current_output_position());
|
||||
next_scan->end_points[1].y = uint16_t(vertical_flywheel_->get_current_output_position() / vertical_flywheel_output_divider_);
|
||||
next_scan->end_points[1].composite_angle = int16_t((phase_numerator_ << 6) / phase_denominator_) * (is_alernate_line_ ? -1 : 1);
|
||||
next_scan->end_points[1].data_offset = uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles);
|
||||
next_scan->end_points[1] = end_point(uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles));
|
||||
scan_target_->end_scan();
|
||||
}
|
||||
|
||||
@ -217,13 +224,15 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, bool vsync_
|
||||
? Outputs::Display::ScanTarget::Event::BeginHorizontalRetrace : Outputs::Display::ScanTarget::Event::EndHorizontalRetrace;
|
||||
scan_target_->announce(
|
||||
event,
|
||||
uint16_t(horizontal_flywheel_->get_current_output_position()),
|
||||
uint16_t(vertical_flywheel_->get_current_output_position() / vertical_flywheel_output_divider_));
|
||||
!(horizontal_flywheel_->is_in_retrace() || vertical_flywheel_->is_in_retrace()),
|
||||
end_point(uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles)));
|
||||
|
||||
// Prepare for the next line.
|
||||
if(next_horizontal_sync_event == Flywheel::SyncEvent::StartRetrace) {
|
||||
is_alernate_line_ ^= phase_alternates_;
|
||||
colour_burst_amplitude_ = 0;
|
||||
} else {
|
||||
cycles_since_horizontal_sync_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,8 +243,8 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, bool vsync_
|
||||
? Outputs::Display::ScanTarget::Event::BeginVerticalRetrace : Outputs::Display::ScanTarget::Event::EndVerticalRetrace;
|
||||
scan_target_->announce(
|
||||
event,
|
||||
uint16_t(horizontal_flywheel_->get_current_output_position()),
|
||||
uint16_t(vertical_flywheel_->get_current_output_position() / vertical_flywheel_output_divider_));
|
||||
!(horizontal_flywheel_->is_in_retrace() || vertical_flywheel_->is_in_retrace()),
|
||||
end_point(uint16_t((total_cycles - number_of_cycles) * number_of_samples / total_cycles)));
|
||||
}
|
||||
|
||||
// if this is vertical retrace then adcance a field
|
||||
|
@ -41,6 +41,8 @@ class CRT {
|
||||
// posted on to the scan target.
|
||||
std::unique_ptr<Flywheel> horizontal_flywheel_, vertical_flywheel_;
|
||||
int vertical_flywheel_output_divider_ = 1;
|
||||
int cycles_since_horizontal_sync_ = 0;
|
||||
Display::ScanTarget::Scan::EndPoint end_point(uint16_t data_offset);
|
||||
|
||||
struct Scan {
|
||||
enum Type {
|
||||
|
@ -222,13 +222,13 @@ void ScanTarget::submit() {
|
||||
allocation_has_failed_ = false;
|
||||
}
|
||||
|
||||
void ScanTarget::announce(Event event, uint16_t x, uint16_t y) {
|
||||
void ScanTarget::announce(Event event, bool is_visible, const Outputs::Display::ScanTarget::Scan::EndPoint &location) {
|
||||
switch(event) {
|
||||
default: break;
|
||||
case ScanTarget::Event::BeginHorizontalRetrace:
|
||||
if(active_line_) {
|
||||
active_line_->end_points[1].x = x;
|
||||
active_line_->end_points[1].y = y;
|
||||
active_line_->end_points[1].x = location.x;
|
||||
active_line_->end_points[1].y = location.y;
|
||||
}
|
||||
break;
|
||||
case ScanTarget::Event::EndHorizontalRetrace: {
|
||||
@ -257,8 +257,8 @@ void ScanTarget::announce(Event event, uint16_t x, uint16_t y) {
|
||||
}
|
||||
|
||||
if(active_line_) {
|
||||
active_line_->end_points[0].x = x;
|
||||
active_line_->end_points[0].y = y;
|
||||
active_line_->end_points[0].x = location.x;
|
||||
active_line_->end_points[0].y = location.y;
|
||||
active_line_->line = write_pointers_.line;
|
||||
}
|
||||
} break;
|
||||
|
@ -53,7 +53,7 @@ class ScanTarget: public Outputs::Display::ScanTarget {
|
||||
uint8_t *begin_data(size_t required_length, size_t required_alignment) override;
|
||||
void end_data(size_t actual_length) override;
|
||||
void submit() override;
|
||||
void announce(Event event, uint16_t x, uint16_t y) override;
|
||||
void announce(Event event, bool is_visible, const Outputs::Display::ScanTarget::Scan::EndPoint &location) override;
|
||||
|
||||
// Extends the definition of a Scan to include two extra fields,
|
||||
// relevant to the way that this scan target processes video.
|
||||
|
@ -228,6 +228,9 @@ struct ScanTarget {
|
||||
///
|
||||
/// It will produce undefined behaviour if signs differ on a single scan.
|
||||
int16_t composite_angle;
|
||||
|
||||
/// Gives the number of cycles since the most recent horizontal retrace ended.
|
||||
uint16_t cycles_since_end_of_horizontal_retrace;
|
||||
} end_points[2];
|
||||
|
||||
/// For composite video, dictates the amplitude of the colour subcarrier as a proportion of
|
||||
@ -284,8 +287,14 @@ struct ScanTarget {
|
||||
EndVerticalRetrace,
|
||||
};
|
||||
|
||||
/// Provides a hint that the named event has occurred.
|
||||
virtual void announce(Event event, uint16_t x, uint16_t y) {}
|
||||
/*!
|
||||
Provides a hint that the named event has occurred.
|
||||
|
||||
@param event The event.
|
||||
@param is_visible @c true if the output stream is visible immediately after this event; @c false otherwise.
|
||||
@param location The location of the event.
|
||||
*/
|
||||
virtual void announce(Event event, bool is_visible, const Scan::EndPoint &location) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
Loading…
Reference in New Issue
Block a user