1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-13 22:32:03 +00:00

Attempts some part of interrupt decision making.

This commit is contained in:
Thomas Harte 2019-10-24 22:33:42 -04:00
parent 77f14fa638
commit f2f98ed60c
2 changed files with 100 additions and 48 deletions

View File

@ -28,20 +28,28 @@ uint8_t MFP68901::read(int address) {
return gpip_direction_;
case 0x03:
LOG("Read: interrupt enable A");
return interrupt_enable_[0];
return uint8_t(interrupt_enable_ >> 8);
case 0x04:
LOG("Read: interrupt enable B");
return interrupt_enable_[1];
return uint8_t(interrupt_enable_);
case 0x05:
LOG("Read: interrupt pending A");
return interrupt_pending_[0];
return uint8_t(interrupt_pending_ >> 8);
case 0x06:
LOG("Read: interrupt pending B");
return interrupt_pending_[1];
case 0x07: LOG("Read: interrupt in-service A"); break;
case 0x08: LOG("Read: interrupt in-service B"); break;
case 0x09: LOG("Read: interrupt mask A"); break;
case 0x0a: LOG("Read: interrupt mask B"); break;
return uint8_t(interrupt_pending_);
case 0x07:
LOG("Read: interrupt in-service A");
return uint8_t(interrupt_in_service_ >> 8);
case 0x08:
LOG("Read: interrupt in-service B");
return uint8_t(interrupt_in_service_);
case 0x09:
LOG("Read: interrupt mask A");
return uint8_t(interrupt_mask_ >> 8);
case 0x0a:
LOG("Read: interrupt mask B");
return uint8_t(interrupt_mask_);
case 0x0b: LOG("Read: vector"); break;
case 0x0c: LOG("Read: timer A control"); break;
case 0x0d: LOG("Read: timer B control"); break;
@ -74,14 +82,30 @@ void MFP68901::write(int address, uint8_t value) {
gpip_direction_ = value;
reevaluate_gpip_interrupts();
break;
case 0x03: LOG("Write: interrupt enable A " << PADHEX(2) << int(value)); break;
case 0x04: LOG("Write: interrupt enable B " << PADHEX(2) << int(value)); break;
case 0x05: LOG("Write: interrupt pending A " << PADHEX(2) << int(value)); break;
case 0x06: LOG("Write: interrupt pending B " << PADHEX(2) << int(value)); break;
case 0x07: LOG("Write: interrupt in-service A " << PADHEX(2) << int(value)); break;
case 0x08: LOG("Write: interrupt in-service B " << PADHEX(2) << int(value)); break;
case 0x09: LOG("Write: interrupt mask A " << PADHEX(2) << int(value)); break;
case 0x0a: LOG("Write: interrupt mask B " << PADHEX(2) << int(value)); break;
case 0x03:
LOG("Write: interrupt enable A " << PADHEX(2) << int(value));
interrupt_enable_ = (interrupt_enable_ & 0x00ff) | (value << 8);
update_interrupts();
break;
case 0x04:
LOG("Write: interrupt enable B " << PADHEX(2) << int(value));
interrupt_enable_ = (interrupt_enable_ & 0xff00) | value;
update_interrupts();
break;
case 0x05: LOG("Write: interrupt pending A (no-op?) " << PADHEX(2) << int(value)); break;
case 0x06: LOG("Write: interrupt pending B (no-op?) " << PADHEX(2) << int(value)); break;
case 0x07: LOG("Write: interrupt in-service A (no-op?) " << PADHEX(2) << int(value)); break;
case 0x08: LOG("Write: interrupt in-service B (no-op?) " << PADHEX(2) << int(value)); break;
case 0x09:
LOG("Write: interrupt mask A " << PADHEX(2) << int(value));
interrupt_mask_ = (interrupt_mask_ & 0x00ff) | (value << 8);
update_interrupts();
break;
case 0x0a:
LOG("Write: interrupt mask B " << PADHEX(2) << int(value));
interrupt_mask_ = (interrupt_mask_ & 0xff00) | value;
update_interrupts();
break;
case 0x0b: LOG("Write: vector " << PADHEX(2) << int(value)); break;
case 0x0c:
case 0x0d: {
@ -211,24 +235,45 @@ uint8_t MFP68901::get_port_output() {
void MFP68901::reevaluate_gpip_interrupts() {
const uint8_t gpip_state = gpip_input_ ^ gpip_active_edge_;
// An interrupt is detected on any falling edge.
if((gpip_state ^ gpip_interrupt_state_) & gpip_interrupt_state_) {
LOG("Should post GPIP interrupt");
const uint8_t new_interrupt_mask = (gpip_state ^ gpip_interrupt_state_) & gpip_interrupt_state_;
if(new_interrupt_mask) {
begin_interrupts(
(new_interrupt_mask & 0x0f) |
((new_interrupt_mask & 0x03) << 2) |
((new_interrupt_mask & 0xc0) << 8)
);
}
gpip_interrupt_state_ = gpip_state;
}
// MARK: - Interrupts
void MFP68901::begin_interrupt(Interrupt interrupt) {
// In service is always set.
interrupt_in_service_[interrupt >> 3] |= 1 << (interrupt & 7);
// Pending is set only if the interrupt is enabled.
// interrupt_pending_[interrupt >> 3] |=
void MFP68901::begin_interrupts(int interrupt) {
interrupt_in_service_ |= interrupt;
update_interrupts();
}
void MFP68901::end_interrupt(Interrupt interrupt) {
// Reset in-service and pending.
void MFP68901::end_interrupts(int interrupt) {
interrupt_in_service_ &= ~interrupt;
update_interrupts();
}
void MFP68901::update_interrupts() {
interrupt_pending_ = interrupt_in_service_ & interrupt_enable_;
interrupt_line_ = interrupt_pending_ & interrupt_mask_;
if(interrupt_line_) {
LOG("Should produce interrupt...");
}
}
bool MFP68901::get_interrupt_line() {
return interrupt_line_;
}
uint16_t MFP68901::acknowledge_interrupt() {
// TODO.
return 0;
}

View File

@ -34,6 +34,9 @@ class MFP68901 {
void set_port_input(uint8_t);
uint8_t get_port_output();
bool get_interrupt_line();
uint16_t acknowledge_interrupt();
private:
// MARK: - Timers
enum class TimerMode {
@ -80,30 +83,34 @@ class MFP68901 {
// So, the designers seem to have wanted to allow for polling and interrupts,
// and then also decided to have some interrupts be able to be completely
// disabled, so that don't even show up for polling.
uint8_t interrupt_in_service_[2] = {0, 0};
uint8_t interrupt_enable_[2] = {0, 0};
uint8_t interrupt_pending_[2] = {0, 0};
uint8_t interrupt_mask_[2] = {0, 0};
int interrupt_in_service_ = 0;
int interrupt_enable_ = 0;
int interrupt_pending_ = 0;
int interrupt_mask_ = 0;
bool interrupt_line_ = false;
enum Interrupt {
GPIP0 = 0,
GPIP1,
GPIP2,
GPIP3,
TimerD,
TimerC,
GPIP4,
GPIP5,
TimerB,
TransmitError,
TransmitBufferEmpty,
ReceiveError,
ReceiveBufferFull,
GPIP6,
GPIP7
GPIP0 = (1 << 0),
GPIP1 = (1 << 1),
GPIP2 = (1 << 2),
GPIP3 = (1 << 3),
TimerD = (1 << 4),
TimerC = (1 << 5),
GPIP4 = (1 << 6),
GPIP5 = (1 << 7),
TimerB = (1 << 8),
TransmitError = (1 << 9),
TransmitBufferEmpty = (1 << 10),
ReceiveError = (1 << 11),
ReceiveBufferFull = (1 << 12),
TimerA = (1 << 13),
GPIP6 = (1 << 14),
GPIP7 = (1 << 15),
};
void begin_interrupt(Interrupt interrupt);
void end_interrupt(Interrupt interrupt);
void begin_interrupts(int interrupt);
void end_interrupts(int interrupt);
void update_interrupts();
};
}