1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 03:29:45 +00:00

Add dummy retrace interrupt.

This commit is contained in:
Thomas Harte 2024-03-21 10:02:56 -04:00
parent a6ec870872
commit 2d6a4d490e
5 changed files with 87 additions and 15 deletions

View File

@ -60,18 +60,24 @@ class ConcreteMachine:
// Hence, required ticks are:
//
// * CPU: 24;
// * video: 12; [TODO]
// * video: 12;
// * timers: 2;
// * audio: 1.
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_timers();
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_cpu(); tick_cpu();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_cpu(); tick_cpu(); tick_video();
tick_timers();
tick_audio();
}
@ -203,6 +209,7 @@ class ConcreteMachine:
void tick_timers() { executor_.bus.tick_timers(); }
void tick_audio() { executor_.bus.tick_audio(); }
void tick_video() { executor_.bus.tick_video(); }
// MARK: - MediaTarget
bool insert_media(const Analyser::Static::Media &) override {

View File

@ -13,6 +13,8 @@
#include "CMOSRAM.hpp"
#include "Keyboard.hpp"
#include "Sound.hpp"
#include "Video.hpp"
namespace Archimedes {
@ -312,26 +314,36 @@ struct InputOutputController {
InputOutputController(InterruptObserverT &observer) :
observer_(observer),
keyboard_(serial_),
sound_(*this)
sound_(*this),
video_(*this, sound_)
{
irq_a_.status = IRQA::SetAlways | IRQA::PowerOnReset;
irq_b_.status = 0x00;
fiq_.status = 0x80; // 'set always'.
i2c_.add_peripheral(&cmos_, 0xa0);
update_sound_interrupt();
update_interrupts();
}
Sound<InputOutputController> &sound() {
return sound_;
}
void update_sound_interrupt() {
Video<InputOutputController, Sound<InputOutputController>> &video() {
return video_;
}
void update_interrupts() {
if(sound_.interrupt()) {
irq_b_.set(IRQB::SoundBufferPointerUsed);
} else {
irq_b_.clear(IRQB::SoundBufferPointerUsed);
}
if(video_.interrupt()) {
irq_a_.set(IRQA::VerticalFlyback);
}
observer_.update_interrupts();
}
@ -374,8 +386,9 @@ private:
I2C::Bus i2c_;
CMOSRAM cmos_;
// Audio.
// Audio and video.
Sound<InputOutputController> sound_;
Video<InputOutputController, Sound<InputOutputController>> video_;
};
}

View File

@ -32,7 +32,7 @@ static_assert(BitMask<15, 14>::value == 49152);
template <typename InterruptObserverT>
struct MemoryController {
MemoryController(InterruptObserverT &observer) :
ioc_(observer), vidc_(observer, ioc_.sound()) {}
ioc_(observer) {}
int interrupt_mask() const {
return ioc_.interrupt_mask();
@ -127,7 +127,7 @@ struct MemoryController {
case Zone::VideoController:
// TODO: handle byte writes correctly.
vidc_.write(source);
ioc_.video().write(source);
break;
case Zone::PhysicallyMappedRAM:
@ -214,6 +214,9 @@ struct MemoryController {
// stop allowing it to use the bus?
ioc_.sound().tick();
}
void tick_video() {
ioc_.video().tick();
}
private:
Log::Logger<Log::Source::ARMIOC> logger;
@ -253,7 +256,6 @@ struct MemoryController {
std::array<uint8_t, 4*1024*1024> ram_{};
std::array<uint8_t, 2*1024*1024> rom_;
InputOutputController<InterruptObserverT> ioc_;
Video<InterruptObserverT, Sound<InputOutputController<InterruptObserverT>>> vidc_;
template <typename IntT>
IntT &physical_ram(uint32_t address) {

View File

@ -88,7 +88,7 @@ private:
void set_buffer_valid(bool valid) {
next_buffer_valid_ = valid;
observer_.update_sound_interrupt();
observer_.update_interrupts();
}
void set_halted(bool halted) {

View File

@ -21,6 +21,9 @@ struct Video {
void write(uint32_t value) {
const auto target = (value >> 24) & 0xfc;
const auto timing_value = [](uint32_t value) -> uint32_t {
return (value >> 14) & 0x3ff;
};
switch(target) {
case 0x00: case 0x04: case 0x08: case 0x0c:
@ -40,24 +43,31 @@ struct Video {
case 0x80:
logger.error().append("TODO: Video horizontal period: %d", (value >> 14) & 0x3ff);
horizontal_.period = timing_value(value);
break;
case 0x84:
logger.error().append("TODO: Video horizontal sync width: %d", (value >> 14) & 0x3ff);
horizontal_.sync_width = timing_value(value);
break;
case 0x88:
logger.error().append("TODO: Video horizontal border start: %d", (value >> 14) & 0x3ff);
horizontal_.border_start = timing_value(value);
break;
case 0x8c:
logger.error().append("TODO: Video horizontal display start: %d", (value >> 14) & 0x3ff);
horizontal_.display_start = timing_value(value);
break;
case 0x90:
logger.error().append("TODO: Video horizontal display end: %d", (value >> 14) & 0x3ff);
horizontal_.display_end = timing_value(value);
break;
case 0x94:
logger.error().append("TODO: Video horizontal border end: %d", (value >> 14) & 0x3ff);
horizontal_.border_end = timing_value(value);
break;
case 0x98:
logger.error().append("TODO: Video horizontal cursor end: %d", (value >> 14) & 0x3ff);
horizontal_.cursor_end = timing_value(value);
break;
case 0x9c:
logger.error().append("TODO: Video horizontal interlace: %d", (value >> 14) & 0x3ff);
@ -65,27 +75,35 @@ struct Video {
case 0xa0:
logger.error().append("TODO: Video vertical period: %d", (value >> 14) & 0x3ff);
vertical_.period = timing_value(value);
break;
case 0xa4:
logger.error().append("TODO: Video vertical sync width: %d", (value >> 14) & 0x3ff);
vertical_.sync_width = timing_value(value);
break;
case 0xa8:
logger.error().append("TODO: Video vertical border start: %d", (value >> 14) & 0x3ff);
vertical_.border_start = timing_value(value);
break;
case 0xac:
logger.error().append("TODO: Video vertical display start: %d", (value >> 14) & 0x3ff);
vertical_.display_start = timing_value(value);
break;
case 0xb0:
logger.error().append("TODO: Video vertical display end: %d", (value >> 14) & 0x3ff);
vertical_.display_end = timing_value(value);
break;
case 0xb4:
logger.error().append("TODO: Video vertical border end: %d", (value >> 14) & 0x3ff);
vertical_.border_end = timing_value(value);
break;
case 0xb8:
logger.error().append("TODO: Video vertical cursor start: %d", (value >> 14) & 0x3ff);
vertical_.cursor_start = timing_value(value);
break;
case 0xbc:
logger.error().append("TODO: Video vertical cursor end: %d", (value >> 14) & 0x3ff);
vertical_.cursor_end = timing_value(value);
break;
case 0xe0:
@ -112,10 +130,42 @@ struct Video {
}
}
void tick() {
++position_;
if(position_ >= horizontal_.period * vertical_.period) {
entered_sync_ = true;
position_ = 0;
observer_.update_interrupts();
}
}
bool interrupt() {
// Guess: edge triggered?
const bool interrupt = entered_sync_;
entered_sync_ = false;
return interrupt;
}
private:
Log::Logger<Log::Source::ARMIOC> logger;
InterruptObserverT &observer_;
SoundT &sound_;
// TODO: real video output.
int position_ = 0;
struct Dimension {
uint32_t period = 0;
uint32_t sync_width = 0;
uint32_t border_start = 0;
uint32_t border_end = 0;
uint32_t display_start = 0;
uint32_t display_end = 0;
uint32_t cursor_start = 0;
uint32_t cursor_end = 0;
};
Dimension horizontal_, vertical_;
bool entered_sync_ = false;
};
}