1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +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:
Thomas Harte 2016-02-12 19:53:49 -05:00
parent 341fafd3c5
commit 0a09762be6
4 changed files with 37 additions and 40 deletions

View File

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

View File

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

View File

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

View File

@ -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.
*/
};