1
0
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:
Thomas Harte 2019-01-05 23:09:17 -05:00
parent 46d756d298
commit e9d9ff0da0
6 changed files with 41 additions and 21 deletions

View File

@ -68,7 +68,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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.

View File

@ -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) {}
};
/*!