]> localhost Git - WindEmu.git/commitdiff
sa1100: hook up peripherals to core
authorGeorge Wright <gw@gwright.org.uk>
Thu, 25 Jun 2026 03:03:41 +0000 (20:03 -0700)
committerGeorge Wright <gw@gwright.org.uk>
Fri, 26 Jun 2026 03:44:48 +0000 (20:44 -0700)
WindCore/series7/sa1100.cpp
WindCore/series7/sa1100.h
WindCore/series7/sa1100_memory.cpp

index ce3135baceb5f0ec0c7ee39fd747d4e0a4d4d24a..c4507118a3678d247e2e687816d2101f217451d3 100644 (file)
@@ -6,7 +6,34 @@
 
 namespace SA1100 {
 
-Emulator::Emulator() : EmuBase(false) {}
+Emulator::Emulator() : EmuBase(false) {
+  mOsTimer = new OsTimer();
+  mLcdController = new LCDController();
+  mGpioController = new GPIOController();
+  mUart = new Uart(getSerialOutput());
+  mResetController = new ResetController();
+  mRtc = new RTC(getClockSpeed());
+  mIntController =
+      new IntController(mLcdController, mOsTimer, mGpioController, mUart, mRtc);
+  mPowerManager = new PowerManager();
+
+  MemoryBlockC0 = new uint8_t[MemoryBlockMask + 1];
+  MemoryBlockC8 = new uint8_t[MemoryBlockMask + 1];
+  ROM = new uint8_t[0x1000000];
+}
+
+Emulator::~Emulator() {
+  delete mOsTimer;
+  delete mLcdController;
+  delete mGpioController;
+  delete mIntController;
+  delete mPowerManager;
+  delete mResetController;
+  delete mRtc;
+  delete[] MemoryBlockC0;
+  delete[] MemoryBlockC8;
+  delete[] ROM;
+}
 
 uint32_t Emulator::getRTC() { return 0; }
 
@@ -17,6 +44,15 @@ void Emulator::configure() {
   configured = true;
   srand(1000);
   nextTickAt = Series7::TICK_INTERVAL;
+  setProcessorID(0x4401A111);
+
+  mMemoryController.reset();
+  mPowerManager->reset();
+  mOsTimer->reset();
+  mLcdController->reset();
+  mIntController->reset();
+  mGpioController->reset();
+  mRtc->reset();
   reset();
 }
 
@@ -30,6 +66,18 @@ void Emulator::executeUntil(int64_t cycles) {
   if (!configured)
     configure();
 
+  if (mResetController->resetRequested()) {
+    mResetController->reset();
+    mMemoryController.reset();
+    mPowerManager->reset();
+    mOsTimer->reset();
+    mLcdController->reset();
+    mIntController->reset();
+    mGpioController->reset();
+    mRtc->reset();
+    reset();
+  }
+
   while (!asleep && passedCycles < cycles) {
     if (passedCycles >= nextTickAt) {
       // increment RTCDIV
@@ -42,6 +90,21 @@ void Emulator::executeUntil(int64_t cycles) {
       nextTickAt += Series7::TICK_INTERVAL;
     }
 
+    mRtc->run(passedCycles);
+    mGpioController->run();
+    mUart->run(passedCycles);
+    mIntController->run();
+    mOsTimer->tick();
+
+    if (mIntController->havePendingFiq() && canAcceptFIQ()) {
+      requestFIQ();
+      halted = false;
+    }
+    if (mIntController->havePendingIrq() && canAcceptIRQ()) {
+      requestIRQ();
+      halted = false;
+    }
+
     // what's running?
     if (halted) {
       // keep the clock moving
index 23d8e100139b4969e462af4c6a3675ca41109338..c73628e7522b5d799d85eaa29afc3ba228b6586e 100644 (file)
@@ -4,6 +4,16 @@
 #include "emubase.h"
 #include "series7_defs.h"
 
+#include "gpio_controller.h"
+#include "interrupt_controller.h"
+#include "lcd_controller.h"
+#include "memory_controller.h"
+#include "os_timer.h"
+#include "power_manager.h"
+#include "reset_controller.h"
+#include "rtc.h"
+#include "uart.h"
+
 namespace SA1100 {
 
 // Relatively simple implementation of a StrongARM SA-1100 CPU
@@ -22,21 +32,30 @@ namespace SA1100 {
 
 class Emulator : public EmuBase {
 public:
-  // 16MB ROM
-  uint8_t ROM[0x1000000];
-  // 16MB RAM/bank0, mapped at base addr 0xC0000000
-  uint8_t MemoryBlockC0[0x1000000];
-  // 16MB RAM/bank1, mapped at base addr 0xC8000000
+  uint8_t* ROM;
+  // RAM/bank0, mapped at base addr 0xC0000000
+  uint8_t* MemoryBlockC0;
+  // RAM/bank1, mapped at base addr 0xC8000000
   // On the netBook, the OS.img minus the 256-byte wrapper is copied to this RAM
   // See the bookboot README file (linked above)
-  uint8_t MemoryBlockC8[0x1000000];
-  enum { MemoryBlockMask = 0x0FFFFFF };
+  uint8_t* MemoryBlockC8;
+  const uint32_t MemoryBlockMask = 0x0FFFFFF;
 
 private:
   uint32_t pwrsr = 0x00002000; // cold start flag
   bool halted = false, asleep = false;
   uint32_t getRTC();
 
+  MemoryController mMemoryController;
+  GPIOController* mGpioController;
+  LCDController* mLcdController;
+  OsTimer* mOsTimer;
+  IntController* mIntController;
+  PowerManager* mPowerManager;
+  ResetController* mResetController;
+  RTC* mRtc;
+  Uart* mUart;
+
 public:
   MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
   bool writePhysical(uint32_t value, uint32_t physAddr,
@@ -75,6 +94,8 @@ private:
 
 public:
   Emulator();
+  virtual ~Emulator();
+
   uint8_t* getROMBuffer() override;
   size_t getROMSize() override;
   void loadROM(uint8_t* buffer, size_t size) override;
index fbb79da7731200e3665abd704c7ffd7f032c3118..443b366b90163da8fa9c78975ce41b046dce2baf 100644 (file)
@@ -30,12 +30,29 @@ uint8_t Emulator::readPCM8(uint32_t physAddr) {
 bool Emulator::writePCM8(uint8_t value, uint32_t physAddr) { return true; }
 
 uint32_t Emulator::readPCM32(uint32_t physAddr) {
-  // Peripheral Control Modules
-  return 0x0;
+  uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+  switch (region) {
+  case 0x8005:
+    // UART
+    return mUart->read32(physAddr);
+  default:
+    return 0x0;
+  }
 }
 
-bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) { return true; }
+bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) {
+  uint16_t region = (physAddr >> 16) & 0xFFFF;
 
+  switch (region) {
+  case 0x8005:
+    // UART
+    mUart->write32(physAddr, value);
+    return true;
+  default:
+    return true;
+  }
+}
 uint8_t Emulator::readSCM8(uint32_t physAddr) {
   // System Control Modules
   return 0x0;
@@ -44,11 +61,72 @@ uint8_t Emulator::readSCM8(uint32_t physAddr) {
 bool Emulator::writeSCM8(uint8_t value, uint32_t physAddr) { return true; }
 
 uint32_t Emulator::readSCM32(uint32_t physAddr) {
-  // System Control Modules
-  return 0x0;
+  uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+  switch (region) {
+  case 0x9000:
+    // OS Timer
+    return mOsTimer->read32(physAddr);
+  case 0x9001:
+    // RTC
+    return mRtc->read32(physAddr);
+  case 0x9002:
+    // Power manager
+    return mPowerManager->read32(physAddr);
+  case 0x9003:
+    // Reset controller
+    return mResetController->read32(physAddr);
+  case 0x9004:
+    // GPIO
+    return mGpioController->read32(physAddr);
+  case 0x9005:
+    // Interrupt Controller
+    return mIntController->read32(physAddr);
+  case 0x9006:
+    // PPC
+    return 0;
+  default:
+    printf("Tried to read %08x\n", physAddr);
+    return 0x0;
+  }
 }
 
-bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) { return true; }
+bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) {
+  uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+  switch (region) {
+  case 0x9000:
+    // OS Timer
+    mOsTimer->write32(physAddr, value);
+    return true;
+  case 0x9001:
+    // RTC
+    mRtc->write32(physAddr, value);
+    return true;
+  case 0x9002:
+    // Power manager
+    mPowerManager->write32(physAddr, value);
+    return true;
+  case 0x9003:
+    // Reset controller
+    mResetController->write32(physAddr, value);
+    return true;
+  case 0x9004:
+    // GPIO
+    mGpioController->write32(physAddr, value);
+    return true;
+  case 0x9005:
+    // Interrupt Controller
+    mIntController->write32(physAddr, value);
+    return true;
+  case 0x9006:
+    // PPC
+    return true;
+  default:
+    LOG_REG_W("Unknown", physAddr, value);
+    return true;
+  }
+}
 
 uint8_t Emulator::readPhysical8(uint32_t physAddr) {
   uint8_t region = (physAddr >> 24) & 0xFF;
@@ -466,11 +544,11 @@ uint32_t Emulator::readPhysical32(uint32_t physAddr) {
     break;
   case 0xA0:
     // Memory Control Registers
-    result = 0x0;
+    result = mMemoryController.read32(physAddr);
     break;
   case 0xB0:
     // LCD/DMA Control Registers
-    result = 0x0;
+    result = mLcdController->read32(physAddr);
     break;
   case 0xC0:
   case 0xC1:
@@ -506,7 +584,6 @@ bool Emulator::writePhysical32(uint32_t value, uint32_t physAddr) {
   case 0x00:
     // Read-only
     return false;
-    break;
   case 0x20:
   case 0x21:
   case 0x22:
@@ -617,9 +694,11 @@ bool Emulator::writePhysical32(uint32_t value, uint32_t physAddr) {
     return writeSCM32(value, physAddr);
   case 0xA0:
     // Memory Control Registers
-    return false;
+    mMemoryController.write32(physAddr, value);
+    return true;
   case 0xB0:
     // LCD/DMA Control Registers
+    mLcdController->write32(physAddr, value);
     return true;
   case 0xC0:
   case 0xC1: