mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-11 04:28:58 +00:00
Fixed output precision compared to the new approach of trusting the flywheel for position, and eliminated fixed-Acorn constants. Also re-enabled the faded previous frame, at least temporarily.
This commit is contained in:
parent
341fafd3c5
commit
0a09762be6
@ -181,12 +181,13 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
#define tex_y(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 2])
|
#define tex_y(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 2])
|
||||||
#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral]
|
#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral]
|
||||||
|
|
||||||
#define InternalToUInt16(v) ((v) + 32768) >> 16
|
#define InternalToUInt16(v) ((v) + 32768) >> 16
|
||||||
|
#define CounterToInternal(c) (unsigned int)(((uint64_t)c->get_current_output_position() * kCRTFixedPointRange) / c->get_scan_period())
|
||||||
|
|
||||||
if(next_run)
|
if(next_run)
|
||||||
{
|
{
|
||||||
unsigned int x_position = _horizontal_flywheel->get_current_output_position() * (kCRTFixedPointRange / 1024);
|
unsigned int x_position = CounterToInternal(_horizontal_flywheel);
|
||||||
unsigned int y_position = (_vertical_flywheel->get_current_output_position() / 312) * (kCRTFixedPointRange / 1024);
|
unsigned int y_position = CounterToInternal(_vertical_flywheel);
|
||||||
|
|
||||||
// set the type, initial raster position and type of this run
|
// set the type, initial raster position and type of this run
|
||||||
position_x(0) = position_x(4) = InternalToUInt16(kCRTFixedPointOffset + x_position + _beamWidth[lengthMask].x);
|
position_x(0) = position_x(4) = InternalToUInt16(kCRTFixedPointOffset + x_position + _beamWidth[lengthMask].x);
|
||||||
@ -218,8 +219,8 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
|
|
||||||
if(next_run)
|
if(next_run)
|
||||||
{
|
{
|
||||||
unsigned int x_position = _horizontal_flywheel->get_current_output_position() * (kCRTFixedPointRange / 1024);
|
unsigned int x_position = CounterToInternal(_horizontal_flywheel);
|
||||||
unsigned int y_position = (_vertical_flywheel->get_current_output_position() / 312) * (kCRTFixedPointRange / 1024);
|
unsigned int y_position = CounterToInternal(_vertical_flywheel);
|
||||||
|
|
||||||
// store the final raster position
|
// store the final raster position
|
||||||
position_x(2) = position_x(3) = InternalToUInt16(kCRTFixedPointOffset + x_position - _beamWidth[lengthMask].x);
|
position_x(2) = position_x(3) = InternalToUInt16(kCRTFixedPointOffset + x_position - _beamWidth[lengthMask].x);
|
||||||
@ -323,7 +324,7 @@ void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider
|
|||||||
|
|
||||||
#pragma mark - Buffer supply
|
#pragma mark - Buffer supply
|
||||||
|
|
||||||
void CRT::allocate_write_area(int required_length)
|
void CRT::allocate_write_area(size_t required_length)
|
||||||
{
|
{
|
||||||
if(_current_frame_builder) _current_frame_builder->allocate_write_area(required_length);
|
if(_current_frame_builder) _current_frame_builder->allocate_write_area(required_length);
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ class CRT {
|
|||||||
|
|
||||||
@param required_length The number of samples to allocate.
|
@param required_length The number of samples to allocate.
|
||||||
*/
|
*/
|
||||||
void allocate_write_area(int required_length);
|
void allocate_write_area(size_t required_length);
|
||||||
|
|
||||||
/*! Gets a pointer for writing to the area created by the most recent call to @c allocate_write_area
|
/*! Gets a pointer for writing to the area created by the most recent call to @c allocate_write_area
|
||||||
for the nominated buffer.
|
for the nominated buffer.
|
||||||
|
@ -105,11 +105,11 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
|
|||||||
|
|
||||||
push_size_uniforms(output_width, output_height);
|
push_size_uniforms(output_width, output_height);
|
||||||
|
|
||||||
// if(_last_drawn_frame != nullptr)
|
if(_last_drawn_frame != nullptr)
|
||||||
// {
|
{
|
||||||
// glUniform1f(_openGL_state->alphaUniform, 0.4f);
|
glUniform1f(_openGL_state->alphaUniform, 0.4f);
|
||||||
// glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices);
|
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices);
|
||||||
// }
|
}
|
||||||
glUniform1f(_openGL_state->alphaUniform, 1.0f);
|
glUniform1f(_openGL_state->alphaUniform, 1.0f);
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW);
|
||||||
|
@ -12,20 +12,14 @@
|
|||||||
namespace Outputs {
|
namespace Outputs {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Provides timing for a two-phase signal consisting of a retrace phase and a scan phase,
|
Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase,
|
||||||
announcing the start and end of retrace.
|
announcing the start and end of retrace and providing the abiliy to read the current
|
||||||
|
scanning position.
|
||||||
|
|
||||||
The flywheel will attempt gradually to converge with the timing implied by
|
The @c Flywheel will attempt to converge with timing implied by synchronisation pulses.
|
||||||
synchronisation requests.
|
|
||||||
*/
|
*/
|
||||||
struct Flywheel
|
struct Flywheel
|
||||||
{
|
{
|
||||||
enum SyncEvent {
|
|
||||||
None,
|
|
||||||
StartRetrace,
|
|
||||||
EndRetrace
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs an instance of @c Flywheel.
|
Constructs an instance of @c Flywheel.
|
||||||
|
|
||||||
@ -36,12 +30,19 @@ struct Flywheel
|
|||||||
Flywheel(unsigned int standard_period, unsigned int retrace_time) :
|
Flywheel(unsigned int standard_period, unsigned int retrace_time) :
|
||||||
_standard_period(standard_period),
|
_standard_period(standard_period),
|
||||||
_retrace_time(retrace_time),
|
_retrace_time(retrace_time),
|
||||||
_sync_error_window(standard_period >> 6),
|
_sync_error_window(standard_period >> 7),
|
||||||
_counter(0),
|
_counter(0),
|
||||||
_expected_next_sync(standard_period),
|
_expected_next_sync(standard_period),
|
||||||
_counter_before_retrace(standard_period - retrace_time),
|
_counter_before_retrace(standard_period - retrace_time) {}
|
||||||
_did_detect_sync(false) {}
|
|
||||||
|
|
||||||
|
enum SyncEvent {
|
||||||
|
/// Indicates that no synchronisation events will occur in the queried window.
|
||||||
|
None,
|
||||||
|
/// Indicates that the next synchronisation event will be a transition into retrce.
|
||||||
|
StartRetrace,
|
||||||
|
/// Indicates that the next synchronisation event will be a transition out of retrace.
|
||||||
|
EndRetrace
|
||||||
|
};
|
||||||
/*!
|
/*!
|
||||||
Asks the flywheel for the first synchronisation event that will occur in a given time period,
|
Asks the flywheel for the first synchronisation event that will occur in a given time period,
|
||||||
indicating whether a synchronisation request occurred at the start of the query window.
|
indicating whether a synchronisation request occurred at the start of the query window.
|
||||||
@ -61,8 +62,6 @@ struct Flywheel
|
|||||||
// do we recognise this hsync, thereby adjusting future time expectations?
|
// do we recognise this hsync, thereby adjusting future time expectations?
|
||||||
if(sync_is_requested)
|
if(sync_is_requested)
|
||||||
{
|
{
|
||||||
_did_detect_sync = true;
|
|
||||||
|
|
||||||
if(_counter < _sync_error_window || _counter > _expected_next_sync - _sync_error_window)
|
if(_counter < _sync_error_window || _counter > _expected_next_sync - _sync_error_window)
|
||||||
{
|
{
|
||||||
unsigned int time_now = (_counter < _sync_error_window) ? _expected_next_sync + _counter : _counter;
|
unsigned int time_now = (_counter < _sync_error_window) ? _expected_next_sync + _counter : _counter;
|
||||||
@ -112,13 +111,6 @@ struct Flywheel
|
|||||||
*/
|
*/
|
||||||
inline void apply_event(unsigned int cycles_advanced, SyncEvent event)
|
inline void apply_event(unsigned int cycles_advanced, SyncEvent event)
|
||||||
{
|
{
|
||||||
if(_counter <= _sync_error_window && _counter + cycles_advanced > _sync_error_window)
|
|
||||||
{
|
|
||||||
if(!_did_detect_sync)
|
|
||||||
_expected_next_sync = (_expected_next_sync + _standard_period + (_sync_error_window >> 1)) >> 1;
|
|
||||||
_did_detect_sync = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_counter += cycles_advanced;
|
_counter += cycles_advanced;
|
||||||
|
|
||||||
switch(event)
|
switch(event)
|
||||||
@ -165,6 +157,14 @@ struct Flywheel
|
|||||||
return _counter < _retrace_time;
|
return _counter < _retrace_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@returns the expected length of the scan period.
|
||||||
|
*/
|
||||||
|
inline unsigned int get_scan_period()
|
||||||
|
{
|
||||||
|
return _standard_period - _retrace_time;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int _standard_period; // the normal length of time between syncs
|
unsigned int _standard_period; // the normal length of time between syncs
|
||||||
const unsigned int _retrace_time; // a constant indicating the amount of time it takes to perform a retrace
|
const unsigned int _retrace_time; // a constant indicating the amount of time it takes to perform a retrace
|
||||||
@ -174,8 +174,6 @@ struct Flywheel
|
|||||||
unsigned int _counter_before_retrace; // the value of _counter immediately before retrace began
|
unsigned int _counter_before_retrace; // the value of _counter immediately before retrace began
|
||||||
unsigned int _expected_next_sync; // our current expection of when the next sync will be encountered (which implies velocity)
|
unsigned int _expected_next_sync; // our current expection of when the next sync will be encountered (which implies velocity)
|
||||||
|
|
||||||
bool _did_detect_sync; // stores whether sync was detected at all during the current iteration
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Implementation notes:
|
Implementation notes:
|
||||||
|
|
||||||
@ -185,10 +183,8 @@ struct Flywheel
|
|||||||
retrace begins and the internal counter is reset.
|
retrace begins and the internal counter is reset.
|
||||||
|
|
||||||
All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
|
All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
|
||||||
expected synchronisation time will cause an adjustment in the expected time for the next synchronisation.
|
expected synchronisation time will cause a proportional adjustment in the expected time for the next
|
||||||
|
synchronisation. Other synchronisation events are clamped as though they occurred in that range.
|
||||||
If no synchronisation event is detected within that window then the amount of time spent in scan
|
|
||||||
will edge towards a period slightly longer than the standard period.
|
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user