mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-08 14:25:05 +00:00
Introduces a latency between DE and load.
This commit is contained in:
@@ -145,6 +145,7 @@ void Video::run_for(HalfCycles duration) {
|
|||||||
if(horizontal_timings.set_blank > x_) next_event = std::min(next_event, horizontal_timings.set_blank);
|
if(horizontal_timings.set_blank > x_) next_event = std::min(next_event, horizontal_timings.set_blank);
|
||||||
if(horizontal_timings.reset_enable > x_) next_event = std::min(next_event, horizontal_timings.reset_enable);
|
if(horizontal_timings.reset_enable > x_) next_event = std::min(next_event, horizontal_timings.reset_enable);
|
||||||
if(horizontal_timings.set_enable > x_) next_event = std::min(next_event, horizontal_timings.set_enable);
|
if(horizontal_timings.set_enable > x_) next_event = std::min(next_event, horizontal_timings.set_enable);
|
||||||
|
if(next_load_toggle_ > x_) next_event = std::min(next_event, next_load_toggle_);
|
||||||
|
|
||||||
// Check for events that are relative to existing latched state.
|
// Check for events that are relative to existing latched state.
|
||||||
if(line_length_ - 50*2 > x_) next_event = std::min(next_event, line_length_ - 50*2);
|
if(line_length_ - 50*2 > x_) next_event = std::min(next_event, line_length_ - 50*2);
|
||||||
@@ -163,14 +164,16 @@ void Video::run_for(HalfCycles duration) {
|
|||||||
shifter_.output_sync(run_length);
|
shifter_.output_sync(run_length);
|
||||||
} else if(horizontal_.blank || vertical_.blank) {
|
} else if(horizontal_.blank || vertical_.blank) {
|
||||||
shifter_.output_blank(run_length);
|
shifter_.output_blank(run_length);
|
||||||
} else if(!vertical_.enable || !horizontal_.enable) {
|
} else if(!load_) {
|
||||||
shifter_.output_border(run_length, output_bpp_);
|
shifter_.output_border(run_length, output_bpp_);
|
||||||
} else {
|
} else {
|
||||||
|
const int since_load = x_ - load_base_;
|
||||||
|
|
||||||
// There will be pixels this line, subject to the shifter pipeline.
|
// There will be pixels this line, subject to the shifter pipeline.
|
||||||
// Divide into 8-[half-]cycle windows; at the start of each window fetch a word,
|
// Divide into 8-[half-]cycle windows; at the start of each window fetch a word,
|
||||||
// and during the rest of the window, shift out.
|
// and during the rest of the window, shift out.
|
||||||
int start_column = x_ >> 3;
|
int start_column = since_load >> 3;
|
||||||
const int end_column = (x_ + run_length) >> 3;
|
const int end_column = (since_load + run_length) >> 3;
|
||||||
|
|
||||||
// Rules obeyed below:
|
// Rules obeyed below:
|
||||||
//
|
//
|
||||||
@@ -182,9 +185,9 @@ void Video::run_for(HalfCycles duration) {
|
|||||||
shifter_.output_pixels(run_length, output_bpp_);
|
shifter_.output_pixels(run_length, output_bpp_);
|
||||||
} else {
|
} else {
|
||||||
// Continue the current column if partway across.
|
// Continue the current column if partway across.
|
||||||
if(x_&7) {
|
if(since_load&7) {
|
||||||
// If at least one column boundary is crossed, complete this column.
|
// If at least one column boundary is crossed, complete this column.
|
||||||
shifter_.output_pixels(8 - (x_ & 7), output_bpp_);
|
shifter_.output_pixels(8 - (since_load & 7), output_bpp_);
|
||||||
++start_column; // This starts a new column, so latch a new word.
|
++start_column; // This starts a new column, so latch a new word.
|
||||||
latch_word();
|
latch_word();
|
||||||
}
|
}
|
||||||
@@ -197,8 +200,8 @@ void Video::run_for(HalfCycles duration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Output the start of the next column, if necessary.
|
// Output the start of the next column, if necessary.
|
||||||
if((x_ + run_length) & 7) {
|
if((since_load + run_length) & 7) {
|
||||||
shifter_.output_pixels((x_ + run_length) & 7, output_bpp_);
|
shifter_.output_pixels((since_load + run_length) & 7, output_bpp_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,8 +251,20 @@ void Video::run_for(HalfCycles duration) {
|
|||||||
else if(horizontal_timings.set_blank == x_) horizontal_.blank = true;
|
else if(horizontal_timings.set_blank == x_) horizontal_.blank = true;
|
||||||
else if(horizontal_timings.reset_enable == x_) horizontal_.enable = false;
|
else if(horizontal_timings.reset_enable == x_) horizontal_.enable = false;
|
||||||
else if(horizontal_timings.set_enable == x_) horizontal_.enable = true;
|
else if(horizontal_timings.set_enable == x_) horizontal_.enable = true;
|
||||||
else if(line_length_ - 50*2 == x_) horizontal_.sync = true;
|
else if(line_length_ - 50*2 == x_) { horizontal_.sync = true; horizontal_.enable = false; }
|
||||||
else if(line_length_ - 10*2 == x_) horizontal_.sync = false;
|
else if(line_length_ - 10*2 == x_) horizontal_.sync = false;
|
||||||
|
else if(next_load_toggle_ == x_) {
|
||||||
|
next_load_toggle_ = -1;
|
||||||
|
load_ ^= true;
|
||||||
|
load_base_ = x_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for an upcoming load toggle — that is, a time at which load_ will be either
|
||||||
|
// disabled or enabled. These are scheduled for four cycles after the event that should
|
||||||
|
// change load has occurred.
|
||||||
|
if((horizontal_.enable && vertical_.enable) != load_ && next_load_toggle_ == -1) {
|
||||||
|
next_load_toggle_ = x_ + 8; // 4 cycles = 8 half-cycles
|
||||||
|
}
|
||||||
|
|
||||||
// Check vertical events.
|
// Check vertical events.
|
||||||
if(vertical_.sync_schedule != VerticalState::SyncSchedule::None && x_ == vsync_x_position) {
|
if(vertical_.sync_schedule != VerticalState::SyncSchedule::None && x_ == vsync_x_position) {
|
||||||
@@ -406,6 +421,8 @@ void Video::write(int address, uint16_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Video::update_output_mode() {
|
void Video::update_output_mode() {
|
||||||
|
// const auto old_frequency = field_frequency_;
|
||||||
|
|
||||||
// If this is black and white mode, that's that.
|
// If this is black and white mode, that's that.
|
||||||
switch((video_mode_ >> 8) & 3) {
|
switch((video_mode_ >> 8) & 3) {
|
||||||
case 0: output_bpp_ = OutputBpp::Four; break;
|
case 0: output_bpp_ = OutputBpp::Four; break;
|
||||||
@@ -416,10 +433,12 @@ void Video::update_output_mode() {
|
|||||||
case 2:
|
case 2:
|
||||||
output_bpp_ = OutputBpp::One;
|
output_bpp_ = OutputBpp::One;
|
||||||
field_frequency_ = FieldFrequency::SeventyTwo;
|
field_frequency_ = FieldFrequency::SeventyTwo;
|
||||||
|
// if(field_frequency_ != old_frequency) {
|
||||||
|
// printf("%d, %d -> %d\n", x_, y_, field_frequency_);
|
||||||
|
// }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const auto old_frequency = field_frequency_;
|
|
||||||
field_frequency_ = (sync_mode_ & 0x200) ? FieldFrequency::Fifty : FieldFrequency::Sixty;
|
field_frequency_ = (sync_mode_ & 0x200) ? FieldFrequency::Fifty : FieldFrequency::Sixty;
|
||||||
// if(field_frequency_ != old_frequency) {
|
// if(field_frequency_ != old_frequency) {
|
||||||
// printf("%d, %d -> %d\n", x_, y_, field_frequency_);
|
// printf("%d, %d -> %d\n", x_, y_, field_frequency_);
|
||||||
|
@@ -116,6 +116,9 @@ class Video {
|
|||||||
uint16_t line_buffer_[256];
|
uint16_t line_buffer_[256];
|
||||||
|
|
||||||
int x_ = 0, y_ = 0, next_y_ = 0;
|
int x_ = 0, y_ = 0, next_y_ = 0;
|
||||||
|
int next_load_toggle_ = -1;
|
||||||
|
bool load_ = false;
|
||||||
|
int load_base_ = 0;
|
||||||
|
|
||||||
uint16_t video_mode_ = 0;
|
uint16_t video_mode_ = 0;
|
||||||
uint16_t sync_mode_ = 0;
|
uint16_t sync_mode_ = 0;
|
||||||
|
Reference in New Issue
Block a user