1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-16 05:27:43 +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_; return gpip_direction_;
case 0x03: case 0x03:
LOG("Read: interrupt enable A"); LOG("Read: interrupt enable A");
return interrupt_enable_[0]; return uint8_t(interrupt_enable_ >> 8);
case 0x04: case 0x04:
LOG("Read: interrupt enable B"); LOG("Read: interrupt enable B");
return interrupt_enable_[1]; return uint8_t(interrupt_enable_);
case 0x05: case 0x05:
LOG("Read: interrupt pending A"); LOG("Read: interrupt pending A");
return interrupt_pending_[0]; return uint8_t(interrupt_pending_ >> 8);
case 0x06: case 0x06:
LOG("Read: interrupt pending B"); LOG("Read: interrupt pending B");
return interrupt_pending_[1]; return uint8_t(interrupt_pending_);
case 0x07: LOG("Read: interrupt in-service A"); break; case 0x07:
case 0x08: LOG("Read: interrupt in-service B"); break; LOG("Read: interrupt in-service A");
case 0x09: LOG("Read: interrupt mask A"); break; return uint8_t(interrupt_in_service_ >> 8);
case 0x0a: LOG("Read: interrupt mask B"); break; 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 0x0b: LOG("Read: vector"); break;
case 0x0c: LOG("Read: timer A control"); break; case 0x0c: LOG("Read: timer A control"); break;
case 0x0d: LOG("Read: timer B 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; gpip_direction_ = value;
reevaluate_gpip_interrupts(); reevaluate_gpip_interrupts();
break; break;
case 0x03: LOG("Write: interrupt enable A " << PADHEX(2) << int(value)); break; case 0x03:
case 0x04: LOG("Write: interrupt enable B " << PADHEX(2) << int(value)); break; LOG("Write: interrupt enable A " << PADHEX(2) << int(value));
case 0x05: LOG("Write: interrupt pending A " << PADHEX(2) << int(value)); break; interrupt_enable_ = (interrupt_enable_ & 0x00ff) | (value << 8);
case 0x06: LOG("Write: interrupt pending B " << PADHEX(2) << int(value)); break; update_interrupts();
case 0x07: LOG("Write: interrupt in-service A " << PADHEX(2) << int(value)); break; break;
case 0x08: LOG("Write: interrupt in-service B " << PADHEX(2) << int(value)); break; case 0x04:
case 0x09: LOG("Write: interrupt mask A " << PADHEX(2) << int(value)); break; LOG("Write: interrupt enable B " << PADHEX(2) << int(value));
case 0x0a: LOG("Write: interrupt mask B " << PADHEX(2) << int(value)); break; 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 0x0b: LOG("Write: vector " << PADHEX(2) << int(value)); break;
case 0x0c: case 0x0c:
case 0x0d: { case 0x0d: {
@@ -211,24 +235,45 @@ uint8_t MFP68901::get_port_output() {
void MFP68901::reevaluate_gpip_interrupts() { void MFP68901::reevaluate_gpip_interrupts() {
const uint8_t gpip_state = gpip_input_ ^ gpip_active_edge_; const uint8_t gpip_state = gpip_input_ ^ gpip_active_edge_;
// An interrupt is detected on any falling edge. // An interrupt is detected on any falling edge.
if((gpip_state ^ gpip_interrupt_state_) & gpip_interrupt_state_) { const uint8_t new_interrupt_mask = (gpip_state ^ gpip_interrupt_state_) & gpip_interrupt_state_;
LOG("Should post GPIP interrupt"); 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; gpip_interrupt_state_ = gpip_state;
} }
// MARK: - Interrupts // MARK: - Interrupts
void MFP68901::begin_interrupt(Interrupt interrupt) { void MFP68901::begin_interrupts(int interrupt) {
// In service is always set. interrupt_in_service_ |= interrupt;
interrupt_in_service_[interrupt >> 3] |= 1 << (interrupt & 7); update_interrupts();
// Pending is set only if the interrupt is enabled.
// interrupt_pending_[interrupt >> 3] |=
} }
void MFP68901::end_interrupt(Interrupt interrupt) { void MFP68901::end_interrupts(int interrupt) {
// Reset in-service and pending. 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); void set_port_input(uint8_t);
uint8_t get_port_output(); uint8_t get_port_output();
bool get_interrupt_line();
uint16_t acknowledge_interrupt();
private: private:
// MARK: - Timers // MARK: - Timers
enum class TimerMode { enum class TimerMode {
@@ -80,30 +83,34 @@ class MFP68901 {
// So, the designers seem to have wanted to allow for polling and interrupts, // 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 // and then also decided to have some interrupts be able to be completely
// disabled, so that don't even show up for polling. // disabled, so that don't even show up for polling.
uint8_t interrupt_in_service_[2] = {0, 0}; int interrupt_in_service_ = 0;
uint8_t interrupt_enable_[2] = {0, 0}; int interrupt_enable_ = 0;
uint8_t interrupt_pending_[2] = {0, 0}; int interrupt_pending_ = 0;
uint8_t interrupt_mask_[2] = {0, 0}; int interrupt_mask_ = 0;
bool interrupt_line_ = false;
enum Interrupt { enum Interrupt {
GPIP0 = 0, GPIP0 = (1 << 0),
GPIP1, GPIP1 = (1 << 1),
GPIP2, GPIP2 = (1 << 2),
GPIP3, GPIP3 = (1 << 3),
TimerD, TimerD = (1 << 4),
TimerC, TimerC = (1 << 5),
GPIP4, GPIP4 = (1 << 6),
GPIP5, GPIP5 = (1 << 7),
TimerB,
TransmitError, TimerB = (1 << 8),
TransmitBufferEmpty, TransmitError = (1 << 9),
ReceiveError, TransmitBufferEmpty = (1 << 10),
ReceiveBufferFull, ReceiveError = (1 << 11),
GPIP6, ReceiveBufferFull = (1 << 12),
GPIP7 TimerA = (1 << 13),
GPIP6 = (1 << 14),
GPIP7 = (1 << 15),
}; };
void begin_interrupt(Interrupt interrupt); void begin_interrupts(int interrupt);
void end_interrupt(Interrupt interrupt); void end_interrupts(int interrupt);
void update_interrupts();
}; };
} }