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() {
// 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;
nextTickAt += TICK_INTERVAL;
pendingInterrupts |= (1<<TINT);
+ asic14->tick();
}
if (passedCycles % TICKS_3_6864_MHZ == 0) {
osTimer->tick();
namespace SA1100 {
- ASIC14::ASIC14() {
+ ASIC14::ASIC14(GPIOController* const gpioController) : mGPIOController(gpioController) {
init_register();
mCurrPlace = 0;
for (int i = 0; i < 0x80; i++)
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;
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);
private:
uint8_t prom[0x80] = {};
int mCurrPlace = 0;
+ GPIOController* mGPIOController;
enum
{
CTRL0 = 0x10000000,
}
public:
- ASIC14();
+ ASIC14(GPIOController* const gpioController);
void run();
void reset();
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
#include "gpio_controller.h"
+#include "interrupt_controller.h"
namespace SA1100 {
void GPIOController::reset() {
m_GPLR &= 0xFFFFFFF;
// 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:
namespace SA1100
{
+class IntController;
+
class GPIOController {
private:
// Normal function
enum {
+ GAFR_ASIC14 = (1 << 10),
GAFR_ACTION_BUTTON = (1 << 18)
};
m_GEDR = 0;
m_GAFR = 0;
}
+
+ IntController* mIntController;
public:
GPIOController() {
init_register();
}
+
+ void setIntController(IntController* intController) {
+ mIntController = intController;
+ }
// Operation
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;
};
typedef enum IntCtrlBitMaskEnum IntCtrlBitMaskEnum;
+ enum
+ {
+ ICIP = 0x90050000,
+ ICMR = 0x90050004,
+ ICLR = 0x90050008,
+ ICCR = 0x9005000C,
+ ICFP = 0x90050010,
+ ICPR = 0x90050020
+ };
private:
// Attribute
// Register location
- enum
- {
- ICIP = 0x90050000,
- ICMR = 0x90050004,
- ICLR = 0x90050008,
- ICCR = 0x9005000C,
- ICFP = 0x90050010,
- ICPR = 0x90050020
- };
// Register
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;
}
//
#include "os_timer.h"
+#include "interrupt_controller.h"
namespace SA1100 {
break;
default:
m_OSSR &= ~(value & 0xF);
+ mIntController->clear_interrupt((value & 0xF) << 26);
break;
}
break;
namespace SA1100 {
+class IntController;
+
class OsTimer {
private:
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;
}
}
}
}
}
+
+ IntController* mIntController;
public:
enum {
OsTimer();
+ void setIntController(IntController* intController) {
+ mIntController = intController;
+ }
+
void reset();
void tick();