1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +00:00

Pulled vertical sync detection entirely outside the loop, and gave it greater perspective.

This commit is contained in:
Thomas Harte 2017-03-06 19:15:33 -05:00
parent ad73379d1c
commit e63229a5e5
2 changed files with 23 additions and 9 deletions

View File

@ -34,9 +34,10 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di
colour_cycle_numerator_ = colour_cycle_numerator; colour_cycle_numerator_ = colour_cycle_numerator;
phase_alternates_ = should_alternate; phase_alternates_ = should_alternate;
is_alernate_line_ &= phase_alternates_; is_alernate_line_ &= phase_alternates_;
cycles_per_line_ = cycles_per_line;
unsigned int multiplied_cycles_per_line = cycles_per_line * time_multiplier_; unsigned int multiplied_cycles_per_line = cycles_per_line * time_multiplier_;
// generate timing values implied by the given arbuments // generate timing values implied by the given arguments
sync_capacitor_charge_threshold_ = ((int)(syncCapacityLineChargeThreshold * cycles_per_line) * 3) / 4; sync_capacitor_charge_threshold_ = ((int)(syncCapacityLineChargeThreshold * cycles_per_line) * 3) / 4;
// create the two flywheels // create the two flywheels
@ -265,16 +266,30 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo
void CRT::output_scan(const Scan *const scan) void CRT::output_scan(const Scan *const scan)
{ {
const bool this_is_sync = (scan->type == Scan::Type::Sync); const bool this_is_sync = (scan->type == Scan::Type::Sync);
const bool is_trailing_edge = (is_receiving_sync_ && !this_is_sync);
const bool is_leading_edge = (!is_receiving_sync_ && this_is_sync); const bool is_leading_edge = (!is_receiving_sync_ && this_is_sync);
is_receiving_sync_ = this_is_sync; is_receiving_sync_ = this_is_sync;
// Accumulate: (i) a total of the amount of time in sync; and (ii) the amount of time since sync.
if(this_is_sync) { cycles_of_sync_ += scan->number_of_cycles; cycles_since_sync_ = 0; }
else cycles_since_sync_ += scan->number_of_cycles;
bool vsync_requested = false;
// If it has been at least half a line since sync ended, then it is safe to decide whether what ended
// was vertical sync.
if(cycles_since_sync_ > (cycles_per_line_ >> 1))
{
// If it was vertical sync, set that flag. If it wasn't, clear the summed amount of sync to avoid
// a mistaken vertical sync due to an aggregate of horizontals.
vsync_requested = (cycles_of_sync_ > sync_capacitor_charge_threshold_);
if(vsync_requested || cycles_of_sync_ < (cycles_per_line_ >> 2))
cycles_of_sync_ = 0;
}
// This introduces a blackout period close to the expected vertical sync point in which horizontal syncs are not // This introduces a blackout period close to the expected vertical sync point in which horizontal syncs are not
// recognised, effectively causing the horizontal flywheel to freewheel during that period. This attempts to seek // recognised, effectively causing the horizontal flywheel to freewheel during that period. This attempts to seek
// the problem that vertical sync otherwise often starts halfway through a scanline, which confuses the horizontal // the problem that vertical sync otherwise often starts halfway through a scanline, which confuses the horizontal
// flywheel. I'm currently unclear whether this is an accurate solution to this problem. // flywheel. I'm currently unclear whether this is an accurate solution to this problem.
const bool hsync_requested = is_leading_edge && !vertical_flywheel_->is_near_expected_sync(); const bool hsync_requested = is_leading_edge && !vertical_flywheel_->is_near_expected_sync();
const bool vsync_requested = is_trailing_edge && (sync_capacitor_charge_level_ >= sync_capacitor_charge_threshold_);
// simplified colour burst logic: if it's within the back porch we'll take it // simplified colour burst logic: if it's within the back porch we'll take it
if(scan->type == Scan::Type::ColourBurst) if(scan->type == Scan::Type::ColourBurst)
@ -293,12 +308,6 @@ void CRT::output_scan(const Scan *const scan)
sync_period_ = is_receiving_sync_ ? (sync_period_ + scan->number_of_cycles) : 0; sync_period_ = is_receiving_sync_ ? (sync_period_ + scan->number_of_cycles) : 0;
advance_cycles(scan->number_of_cycles, hsync_requested, vsync_requested, scan->type); advance_cycles(scan->number_of_cycles, hsync_requested, vsync_requested, scan->type);
// either charge or deplete the vertical retrace capacitor (making sure it stops at 0)
if(this_is_sync)
sync_capacitor_charge_level_ += scan->number_of_cycles;
else
sync_capacitor_charge_level_ = std::max(sync_capacitor_charge_level_ - (int)scan->number_of_cycles, 0);
} }
/* /*

View File

@ -94,6 +94,11 @@ class CRT {
enqueued_openGL_functions_.push_back(function); enqueued_openGL_functions_.push_back(function);
} }
// sync counter, for determining vertical sync
unsigned int cycles_of_sync_;
unsigned int cycles_since_sync_;
unsigned int cycles_per_line_;
public: public:
/*! Constructs the CRT with a specified clock rate, height and colour subcarrier frequency. /*! Constructs the CRT with a specified clock rate, height and colour subcarrier frequency.
The requested number of buffers, each with the requested number of bytes per pixel, The requested number of buffers, each with the requested number of bytes per pixel,