mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-11 14:37:37 +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
Outputs/CRT
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user