1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-03 22:33:29 +00:00

Enable various ADB-controller interrupts.

This commit is contained in:
Thomas Harte 2023-08-21 15:35:13 -04:00
parent b5dc84c431
commit bb84a5a474
3 changed files with 26 additions and 12 deletions

View File

@ -68,11 +68,9 @@ void Executor::set_interrupt_line(bool line) {
// is active, amongst other things.
if(interrupt_line_ != line) {
interrupt_line_ = line;
// TODO: verify interrupt connection. Externally, but stubbed off here.
// if(!interrupt_disable_ && line) {
// perform_interrupt<false>(0x1ff4);
// }
if(line) {
set_interrupt_request(interrupt_control_, 0x02, 0x1ff4);
}
}
}
@ -225,6 +223,13 @@ template<bool is_brk> inline void Executor::perform_interrupt(uint16_t vector) {
set_program_counter(uint16_t(memory_[vector] | (memory_[vector+1] << 8)));
}
void Executor::set_interrupt_request(uint8_t &reg, uint8_t value, uint16_t vector) {
reg |= value;
if(!interrupt_disable_ && (reg & (value >> 1))) {
perform_interrupt<false>(vector);
}
}
template <Operation operation, AddressingMode addressing_mode> void Executor::perform() {
// Post cycle cost; this emulation _does not provide accurate timing_.
#define TLength(mode, base) case AddressingMode::mode: subtract_duration(base + t_lengths[index_mode_]); break;
@ -789,12 +794,17 @@ inline void Executor::subtract_duration(int duration) {
// this additional divide by 4 produces the correct net divide by 16.
timer_divider_ += duration;
const int t12_ticks = update_timer(prescalers_[0], timer_divider_ / t12_divider);
const int clock_ticks = timer_divider_ / t12_divider;
timer_divider_ &= (t12_divider-1);
// Update timers 1 and 2. TODO: interrupts (elsewhere?).
if(update_timer(timers_[0], t12_ticks)) interrupt_control_ |= 0x20;
if(update_timer(timers_[1], t12_ticks)) interrupt_control_ |= 0x08;
// Update timers 1 and 2.
const int t12_ticks = update_timer(prescalers_[0], timer_divider_ / t12_divider);
if(update_timer(timers_[0], t12_ticks)) {
set_interrupt_request(interrupt_control_, 0x20, 0x1ff8);
}
if(update_timer(timers_[1], t12_ticks)) {
set_interrupt_request(interrupt_control_, 0x08, 0x1ff6);
}
// If timer X is disabled, stop.
if(timer_control_&0x20) {
@ -804,9 +814,10 @@ inline void Executor::subtract_duration(int duration) {
// Update timer X prescaler.
switch(timer_control_ & 0x0c) {
default: {
const int tx_ticks = update_timer(prescalers_[1], t12_ticks); // TODO: don't hard code this. And is this even right?
if(update_timer(timers_[2], tx_ticks))
timer_control_ |= 0x80; // TODO: interrupt result of this.
const int tx_ticks = update_timer(prescalers_[1], clock_ticks);
if(update_timer(timers_[2], tx_ticks)) {
set_interrupt_request(timer_control_, 0x80, 0x1ffa);
}
} break;
case 0x04:
LOG("TODO: Timer X; Pulse output mode");

View File

@ -165,6 +165,8 @@ class Executor: public CachingExecutor {
template<bool is_brk> inline void perform_interrupt(uint16_t vector);
inline void set_port_output(int port);
void set_interrupt_request(uint8_t &reg, uint8_t value, uint16_t vector);
// MARK: - Execution time
Cycles cycles_;

View File

@ -289,5 +289,6 @@ void GLU::run_ports_for(Cycles cycles) {
}
void GLU::set_vertical_blank(bool is_blank) {
vertical_blank_ = is_blank;
executor_.set_interrupt_line(is_blank);
}