From f2f98ed60c5278736bb3bdaf4201469fff576fd2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 24 Oct 2019 22:33:42 -0400 Subject: [PATCH] Attempts some part of interrupt decision making. --- Components/68901/MFP68901.cpp | 99 +++++++++++++++++++++++++---------- Components/68901/MFP68901.hpp | 49 +++++++++-------- 2 files changed, 100 insertions(+), 48 deletions(-) diff --git a/Components/68901/MFP68901.cpp b/Components/68901/MFP68901.cpp index e0a127cf9..8f1e10ca0 100644 --- a/Components/68901/MFP68901.cpp +++ b/Components/68901/MFP68901.cpp @@ -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; } diff --git a/Components/68901/MFP68901.hpp b/Components/68901/MFP68901.hpp index e69519e49..b56756a08 100644 --- a/Components/68901/MFP68901.hpp +++ b/Components/68901/MFP68901.hpp @@ -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(); }; }