From: George Wright Date: Sat, 7 Dec 2024 23:57:55 +0000 (-0800) Subject: hook up asic14 to gpio pin 10 and fix interrupt status clearing. when an interrupt... X-Git-Url: http://git.gwright.org.uk/?a=commitdiff_plain;h=7db060312d3e884ae28d161aceaa60cd91cf5213;p=WindEmu.git hook up asic14 to gpio pin 10 and fix interrupt status clearing. when an interrupt is serviced, the status is cleared at the source (e.g. by clearing the interrupt status bit on the GPIO controller peripheral). The peripheral itself then clears the appropriate pending interrupt bits on the interrupt controller's status registers. --- diff --git a/WindCore/sa1100.cpp b/WindCore/sa1100.cpp index 1f7d235..5693bcb 100644 --- a/WindCore/sa1100.cpp +++ b/WindCore/sa1100.cpp @@ -13,13 +13,15 @@ Emulator::Emulator() : EmuBase(false) { resetController = new ResetController(); rtc = new RTC(); intController = new IntController(lcdController, osTimer, gpioController, serial3, rtc); + gpioController->setIntController(intController); + osTimer->setIntController(intController); powerManager = new PowerManager(); MemoryBlockC0 = new uint8_t[memoryMask+1]; MemoryBlockC8 = new uint8_t[memoryMask+1]; // MemoryBlockD0 = new uint8_t[memoryMask+1]; // MemoryBlockD8 = new uint8_t[memoryMask+1]; ROM = new uint8_t[0x1000000]; - asic14 = new ASIC14(); + asic14 = new ASIC14(gpioController); } Emulator::~Emulator() { @@ -130,10 +132,12 @@ uint32_t Emulator::readSCM32(uint32_t physAddr) { // GPIO printf("GPIO read at 0x%08x\n", physAddr); return gpioController->get_data(physAddr); - case 0x9005: + case 0x9005: { // Interrupt Controller - printf("Interrupt controller read at 0x%08x\n", physAddr); - return intController->get_data(physAddr); + auto value = intController->get_data(physAddr); + printf("Interrupt controller read at 0x%08x [0x%08x]\n", physAddr, value); + return value; + } default: printf("Read SCM32 at 0x%08x\n", physAddr); return 0x0; @@ -1007,6 +1011,7 @@ bool Emulator::executeUntil(int64_t cycles) { nextTickAt += TICK_INTERVAL; pendingInterrupts |= (1<tick(); } if (passedCycles % TICKS_3_6864_MHZ == 0) { osTimer->tick(); diff --git a/WindCore/sa1100/asic14.cpp b/WindCore/sa1100/asic14.cpp index f6bf18e..cf23854 100644 --- a/WindCore/sa1100/asic14.cpp +++ b/WindCore/sa1100/asic14.cpp @@ -2,7 +2,7 @@ namespace SA1100 { - ASIC14::ASIC14() { + ASIC14::ASIC14(GPIOController* const gpioController) : mGPIOController(gpioController) { init_register(); mCurrPlace = 0; for (int i = 0; i < 0x80; i++) @@ -65,7 +65,7 @@ namespace SA1100 { switch (address) { case CTRL0: printf("ASIC14 read register CTRL0: %04x\n", m_CTRL0); - return m_CTRL0; + return 0; case KBD_PADR: printf("ASIC14 read register KBD_PADR: %04x\n", m_KBD_PADR); return m_KBD_PADR; @@ -129,7 +129,7 @@ namespace SA1100 { break; case CTRL_STATUS: printf("ASIC14 write %04x to register CTRL_STATUS\n", value); - m_CTRL_STATUS = value; + m_CTRL_STATUS &= ~value; break; case POWER: printf("ASIC14 write %04x to register POWER\n", value); diff --git a/WindCore/sa1100/asic14.h b/WindCore/sa1100/asic14.h index 7397e9d..f901774 100644 --- a/WindCore/sa1100/asic14.h +++ b/WindCore/sa1100/asic14.h @@ -42,6 +42,7 @@ class ASIC14 { private: uint8_t prom[0x80] = {}; int mCurrPlace = 0; + GPIOController* mGPIOController; enum { CTRL0 = 0x10000000, @@ -99,7 +100,7 @@ class ASIC14 { } public: - ASIC14(); + ASIC14(GPIOController* const gpioController); void run(); void reset(); @@ -107,6 +108,14 @@ class ASIC14 { uint16_t get_data(uint32_t const address); void put_data(uint32_t const address, uint16_t const value); + void tick() { + + //m_IRQ_STATUS = IRQ_CFCARD_CHANGE | IRQ_PCMCIA_CHANGE; + m_IRQ_STATUS = m_IRQ_MASK; + if (m_IRQ_STATUS != 0) { + mGPIOController->trigger_asic14_gpio(); + } + } }; } // namespace SA1100 diff --git a/WindCore/sa1100/gpio_controller.cpp b/WindCore/sa1100/gpio_controller.cpp index d3c20ba..477d328 100644 --- a/WindCore/sa1100/gpio_controller.cpp +++ b/WindCore/sa1100/gpio_controller.cpp @@ -17,6 +17,7 @@ #include "gpio_controller.h" +#include "interrupt_controller.h" namespace SA1100 { void GPIOController::reset() { m_GPLR &= 0xFFFFFFF; @@ -126,6 +127,8 @@ namespace SA1100 { // GEDR status bits are cleared by writing a one to them. // Writing a zero to a GEDR status bit has no effect. m_GEDR &= ~(value & 0xFFFFFFF); + printf("GEDR write %08x [%08x]\n", value, m_GEDR); + mIntController->clear_interrupt(IntController::GPIO_0_10_EDGE_BIT_MASK); break; case GAFR: diff --git a/WindCore/sa1100/gpio_controller.h b/WindCore/sa1100/gpio_controller.h index b2af1d1..d9668c5 100644 --- a/WindCore/sa1100/gpio_controller.h +++ b/WindCore/sa1100/gpio_controller.h @@ -23,6 +23,8 @@ namespace SA1100 { +class IntController; + class GPIOController { private: @@ -42,6 +44,7 @@ class GPIOController { // Normal function enum { + GAFR_ASIC14 = (1 << 10), GAFR_ACTION_BUTTON = (1 << 18) }; @@ -85,6 +88,8 @@ class GPIOController { m_GEDR = 0; m_GAFR = 0; } + + IntController* mIntController; public: @@ -93,6 +98,10 @@ class GPIOController { GPIOController() { init_register(); } + + void setIntController(IntController* intController) { + mIntController = intController; + } // Operation @@ -124,6 +133,23 @@ class GPIOController { m_GPLR &= ~GAFR_ACTION_BUTTON; } } + + inline void trigger_asic14_gpio() { + printf("Triggering ASIC14 GPIO\n"); + // :SA-1110 Developer's Manual: p.80: Wei 2004-Jul-1: + // + // A zero in GAFR indicates that the corresponding GPIO pin is to be used for its normal GPIO function. + if (0 == (m_GAFR & GAFR_ASIC14)) + { + // if (high) { + // m_GPLR |= GAFR_ASIC14; + // } else { + // m_GPLR &= ~GAFR_ASIC14; + // } + m_GEDR |= GAFR_ASIC14; + } + } + inline void flip_gpio() { if (m_GPLR & 0x400) { m_GPLR &= ~0x400; diff --git a/WindCore/sa1100/interrupt_controller.h b/WindCore/sa1100/interrupt_controller.h index 06dd8ff..cbb0fc2 100644 --- a/WindCore/sa1100/interrupt_controller.h +++ b/WindCore/sa1100/interrupt_controller.h @@ -78,6 +78,15 @@ class IntController { }; typedef enum IntCtrlBitMaskEnum IntCtrlBitMaskEnum; + enum + { + ICIP = 0x90050000, + ICMR = 0x90050004, + ICLR = 0x90050008, + ICCR = 0x9005000C, + ICFP = 0x90050010, + ICPR = 0x90050020 + }; private: // Attribute @@ -89,15 +98,6 @@ class IntController { // Register location - enum - { - ICIP = 0x90050000, - ICMR = 0x90050004, - ICLR = 0x90050008, - ICCR = 0x9005000C, - ICFP = 0x90050010, - ICPR = 0x90050020 - }; // Register @@ -147,6 +147,12 @@ class IntController { void put_data(uint32_t const address, uint32_t const value); + void clear_interrupt(uint32_t const mask) { + m_ICIP = m_ICIP & ~mask; + m_ICFP = m_ICFP & ~mask; + m_ICPR = m_ICPR & ~mask; + printf("Clear interrupt %08x [%08x, %08x]\n", mask, m_ICIP, m_ICFP); + } inline bool have_pending_irq() const { return (0 == m_ICIP) ? false : true; } diff --git a/WindCore/sa1100/os_timer.cpp b/WindCore/sa1100/os_timer.cpp index 10bc5e5..d55ef7e 100644 --- a/WindCore/sa1100/os_timer.cpp +++ b/WindCore/sa1100/os_timer.cpp @@ -16,6 +16,7 @@ // #include "os_timer.h" +#include "interrupt_controller.h" namespace SA1100 { @@ -139,6 +140,7 @@ namespace SA1100 { break; default: m_OSSR &= ~(value & 0xF); + mIntController->clear_interrupt((value & 0xF) << 26); break; } break; diff --git a/WindCore/sa1100/os_timer.h b/WindCore/sa1100/os_timer.h index 3e10a6b..ac66ce6 100644 --- a/WindCore/sa1100/os_timer.h +++ b/WindCore/sa1100/os_timer.h @@ -23,6 +23,8 @@ namespace SA1100 { +class IntController; + class OsTimer { private: @@ -51,16 +53,19 @@ class OsTimer { inline void compare_and_set_status(uint32_t osmrs) { if (osmrs & OSMR0_MASK) { if (m_OSCR == m_OSMR[0]) { + printf("OSMR0 triggered\n"); m_OSSR |= OSMR0_MASK; } } if (osmrs & OSMR1_MASK) { if (m_OSCR == m_OSMR[1]) { + printf("OSMR1 triggered\n"); m_OSSR |= OSMR1_MASK; } } if (osmrs & OSMR2_MASK) { if (m_OSCR == m_OSMR[2]) { + printf("OSMR2 triggered\n"); m_OSSR |= OSMR2_MASK; } } @@ -75,6 +80,8 @@ class OsTimer { } } } + + IntController* mIntController; public: enum { @@ -97,6 +104,10 @@ class OsTimer { OsTimer(); + void setIntController(IntController* intController) { + mIntController = intController; + } + void reset(); void tick();