mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Add dummy retrace interrupt.
This commit is contained in:
parent
a6ec870872
commit
2d6a4d490e
@ -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 {
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user