From 0a09762be6056d181f9822c506e121d657d1097a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 12 Feb 2016 19:53:49 -0500 Subject: [PATCH] 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. --- Outputs/CRT/CRT.cpp | 13 +++++----- Outputs/CRT/CRT.hpp | 2 +- Outputs/CRT/CRTOpenGL.cpp | 10 ++++---- Outputs/CRT/Flywheel.hpp | 52 ++++++++++++++++++--------------------- 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 1bdee8b5f..008a16080 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -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 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) { - unsigned int x_position = _horizontal_flywheel->get_current_output_position() * (kCRTFixedPointRange / 1024); - unsigned int y_position = (_vertical_flywheel->get_current_output_position() / 312) * (kCRTFixedPointRange / 1024); + unsigned int x_position = CounterToInternal(_horizontal_flywheel); + unsigned int y_position = CounterToInternal(_vertical_flywheel); // set the type, initial raster position and type of this run 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) { - unsigned int x_position = _horizontal_flywheel->get_current_output_position() * (kCRTFixedPointRange / 1024); - unsigned int y_position = (_vertical_flywheel->get_current_output_position() / 312) * (kCRTFixedPointRange / 1024); + unsigned int x_position = CounterToInternal(_horizontal_flywheel); + unsigned int y_position = CounterToInternal(_vertical_flywheel); // store the final raster position 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 -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); } diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 6888c320b..9162eac18 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -153,7 +153,7 @@ class CRT { @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 for the nominated buffer. diff --git a/Outputs/CRT/CRTOpenGL.cpp b/Outputs/CRT/CRTOpenGL.cpp index 68db5765c..7da1bb85e 100644 --- a/Outputs/CRT/CRTOpenGL.cpp +++ b/Outputs/CRT/CRTOpenGL.cpp @@ -105,11 +105,11 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool push_size_uniforms(output_width, output_height); -// if(_last_drawn_frame != nullptr) -// { -// glUniform1f(_openGL_state->alphaUniform, 0.4f); -// glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices); -// } + if(_last_drawn_frame != nullptr) + { + glUniform1f(_openGL_state->alphaUniform, 0.4f); + glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices); + } 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); diff --git a/Outputs/CRT/Flywheel.hpp b/Outputs/CRT/Flywheel.hpp index 2dc70703b..c8bf73339 100644 --- a/Outputs/CRT/Flywheel.hpp +++ b/Outputs/CRT/Flywheel.hpp @@ -12,20 +12,14 @@ namespace Outputs { /*! - Provides timing for a two-phase signal consisting of a retrace phase and a scan phase, - announcing the start and end of retrace. + Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase, + 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 - synchronisation requests. + The @c Flywheel will attempt to converge with timing implied by synchronisation pulses. */ struct Flywheel { - enum SyncEvent { - None, - StartRetrace, - EndRetrace - }; - /*! Constructs an instance of @c Flywheel. @@ -36,12 +30,19 @@ struct Flywheel Flywheel(unsigned int standard_period, unsigned int retrace_time) : _standard_period(standard_period), _retrace_time(retrace_time), - _sync_error_window(standard_period >> 6), + _sync_error_window(standard_period >> 7), _counter(0), _expected_next_sync(standard_period), - _counter_before_retrace(standard_period - retrace_time), - _did_detect_sync(false) {} + _counter_before_retrace(standard_period - retrace_time) {} + 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, 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? if(sync_is_requested) { - _did_detect_sync = true; - 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; @@ -112,13 +111,6 @@ struct Flywheel */ 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; switch(event) @@ -165,6 +157,14 @@ struct Flywheel return _counter < _retrace_time; } + /*! + @returns the expected length of the scan period. + */ + inline unsigned int get_scan_period() + { + return _standard_period - _retrace_time; + } + private: 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 @@ -174,8 +174,6 @@ struct Flywheel 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) - bool _did_detect_sync; // stores whether sync was detected at all during the current iteration - /* Implementation notes: @@ -185,10 +183,8 @@ struct Flywheel retrace begins and the internal counter is reset. 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. - - 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. + 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. */ };