diff --git a/qtBuildSystem/Mu/Mu.pro b/qtBuildSystem/Mu/Mu.pro index 1663f3c..6e41fbd 100644 --- a/qtBuildSystem/Mu/Mu.pro +++ b/qtBuildSystem/Mu/Mu.pro @@ -23,7 +23,8 @@ DEFINES += QT_DEPRECATED_WARNINGS DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 CONFIG(debug, debug|release){ - DEFINES += FRONTEND_DEBUG EMU_DEBUG EMU_OPCODE_LEVEL_DEBUG EMU_LOG_REGISTER_ACCESS_UNKNOWN EMU_LOG_APIS + DEFINES += FRONTEND_DEBUG EMU_DEBUG EMU_OPCODE_LEVEL_DEBUG EMU_LOG_REGISTER_ACCESS_UNKNOWN +# EMU_LOG_APIS } INCLUDEPATH += $$PWD/qt-common/include diff --git a/src/emulator.c b/src/emulator.c index 233c6d2..7ab95c6 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -187,7 +187,6 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF #endif resetHwRegisters(); lowPowerStopActive = false; - palmCrystalCycles = 2.0 * (14.0 * (71.0/*p*/ + 1.0) + 3.0/*q*/ + 1.0) / 2.0/*prescaler1*/; palmCycleCounter = 0.0; //memory diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index 3ad1dc3..7ce23e9 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -19,8 +19,9 @@ double timer2CycleCounter; bool pllIsOn(); -void checkInterrupts(); -void checkPortDInterrupts(); +static void checkInterrupts(); +static void checkPortDInterrupts(); +static void recalculateCpuSpeed(); #include "hardwareRegistersAccessors.c.h" #include "hardwareRegistersTiming.c.h" @@ -53,6 +54,8 @@ int interruptAcknowledge(int intLevel){ vector = vectorOffset | intLevel; lowPowerStopActive = false; + registerArrayWrite8(PCTLR, registerArrayRead8(PCTLR) & 0x1F); + recalculateCpuSpeed(); //the interrupt should only be cleared after its been handled @@ -86,6 +89,22 @@ void setPrivilegeViolation(){ registerArrayWrite8(SCR, scr | 0x20); } +static void recalculateCpuSpeed(){ + uint16_t pllfsr = registerArrayRead16(PLLFSR); + uint8_t pctlr = registerArrayRead8(PCTLR); + double prescaler1 = (registerArrayRead16(PLLCR) & 0x0080) ? 2.0 : 1.0; + double p = pllfsr & 0x00FF; + double q = (pllfsr & 0x0F00) >> 8; + double newCpuSpeed = 2.0 * (14.0 * (p + 1.0) + q + 1.0) / prescaler1; + + if(pctlr & 0x80) + newCpuSpeed *= (double)(pctlr & 0x1F) / 31.0; + + debugLog("New CPU frequency of:%f cycles per second.\n", newCpuSpeed * CRYSTAL_FREQUENCY); + debugLog("New CLK32 cycle count of:%f.\n", newCpuSpeed); + palmCrystalCycles = newCpuSpeed; +} + static inline void pllWakeCpuIfOff(){ uint16_t pllcr = registerArrayRead16(PLLCR); if(!pllIsOn() && pllWakeWait == -1){ @@ -111,7 +130,7 @@ static inline void pllWakeCpuIfOff(){ } } -void checkInterrupts(){ +static void checkInterrupts(){ uint32_t activeInterrupts = registerArrayRead32(ISR); uint16_t interruptLevelControlRegister = registerArrayRead16(ILCR); uint16_t portDEdgeSelect = registerArrayRead16(PDIRQEG); @@ -229,7 +248,7 @@ void checkInterrupts(){ m68k_set_irq(intLevel);//should be called even if intLevel is 0, that is how the interrupt state gets cleared } -void checkPortDInterrupts(){ +static void checkPortDInterrupts(){ uint8_t portDValue = getPortDValue(); uint8_t portDDir = registerArrayRead8(PDDIR); uint8_t portDIntEnable = registerArrayRead8(PDIRQEN); @@ -489,6 +508,11 @@ void setHwRegister8(unsigned int address, unsigned int value){ case SCR: setScr(value); break; + + case PCTLR: + registerArrayWrite8(address, value & 0x9F); + recalculateCpuSpeed(); + break; case IVR: //write without the bottom 3 bits @@ -658,11 +682,19 @@ void setHwRegister16(unsigned int address, unsigned int value){ break; case PLLFSR: - setPllfsr16(value); + setPllfsr(value); break; case PLLCR: - setPllcr(value); + //values that matter are disable PLL, prescaler 1 and wakeselect + registerArrayWrite16(PLLCR, value & 0x3FBB); + recalculateCpuSpeed(); + + if(value & 0x0008){ + //The PLL shuts down 30 clock cycles of SYSCLK after the DISPLL bit is set in the PLLCR + m68k_modify_timeslice(-m68k_cycles_remaining() + 30); + debugLog("Disable PLL set, CPU off in 30 cycles!\n"); + } break; case ICR: @@ -937,6 +969,8 @@ void resetHwRegisters(){ //add register settings to misc I/O updateAlarmLedStatus(); updateVibratorStatus(); + + recalculateCpuSpeed(); } void setRtc(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds){ diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 2cf6fb7..0b64d80 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -150,35 +150,12 @@ static inline void setCsctrl1(uint16_t value){ //csctrl 2 and 3 only deal with timing and bus transfer size -static inline void setPllfsr16(uint16_t value){ +static inline void setPllfsr(uint16_t value){ uint16_t oldPllfsr = registerArrayRead16(PLLFSR); if(!(oldPllfsr & 0x4000)){ //frequency protect bit not set registerArrayWrite16(PLLFSR, (value & 0x4FFF) | (oldPllfsr & 0x8000));//preserve CLK32 bit - double prescaler1 = (registerArrayRead16(PLLCR) & 0x0080) ? 2.0 : 1.0; - double p = value & 0x00FF; - double q = (value & 0x0F00) >> 8; - palmCrystalCycles = 2.0 * (14.0 * (p + 1.0) + q + 1.0) / prescaler1; - debugLog("New CPU frequency of:%f cycles per second.\n", CPU_FREQUENCY); - debugLog("New CLK32 cycle count of:%f.\n", palmCrystalCycles); - } -} - -static inline void setPllcr(uint16_t value){ - //values that matter are disable PLL, prescaler 1 and possibly wakeselect - registerArrayWrite16(PLLCR, value & 0x3FBB); - uint16_t pllfsr = registerArrayRead16(PLLFSR); - double prescaler1 = (value & 0x0080) ? 2.0 : 1.0; - double p = pllfsr & 0x00FF; - double q = (pllfsr & 0x0F00) >> 8; - palmCrystalCycles = 2.0 * (14.0 * (p + 1.0) + q + 1.0) / prescaler1; - debugLog("New CPU frequency of:%f cycles per second.\n", CPU_FREQUENCY); - debugLog("New CLK32 cycle count of:%f.\n", palmCrystalCycles); - - if(value & 0x0008){ - //The PLL shuts down 30 clock cycles of SYSCLK after the DISPLL bit is set in the PLLCR - m68k_modify_timeslice(-m68k_cycles_remaining() + 30); - debugLog("Disable PLL set, CPU off in 30 cycles!\n"); + recalculateCpuSpeed(); } } diff --git a/src/sed1376.c b/src/sed1376.c index f719fe2..640b736 100644 --- a/src/sed1376.c +++ b/src/sed1376.c @@ -296,8 +296,8 @@ void sed1376Render(){ for(uint16_t pixelX = 0; pixelX < 160; pixelX++) palmFramebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY); - //debugLog("Screen start address:0x%08X, buffer width:%d, swivel view:%d degrees\n", screenStartAddress, lineSize, rotation); - //debugLog("Screen format, color:%s, BPP:%d\n", color ? "true" : "false", bitDepth); + debugLog("Screen start address:0x%08X, buffer width:%d, swivel view:%d degrees\n", screenStartAddress, lineSize, rotation); + debugLog("Screen format, color:%s, BPP:%d\n", color ? "true" : "false", bitDepth); if(pictureInPictureEnabled){ uint16_t pipStartX = sed1376Registers[PIP_X_START_1] << 8 | sed1376Registers[PIP_X_START_0]; @@ -312,7 +312,7 @@ void sed1376Render(){ pipStartY *= 32 / bitDepth; pipEndY *= 32 / bitDepth; } - //debugLog("PIP state, start x:%d, end x:%d, start y:%d, end y:%d\n", pipStartX, pipEndX, pipStartY, pipEndY); + debugLog("PIP state, start x:%d, end x:%d, start y:%d, end y:%d\n", pipStartX, pipEndX, pipStartY, pipEndY); if(pipStartX < 160 && pipStartY < 160){ pipEndX = pipEndX < 160 ? pipEndX : 160; pipEndY = pipEndY < 160 ? pipEndY : 160; diff --git a/unimplementedFeatures.txt b/unimplementedFeatures.txt index e8809e0..084ca75 100644 --- a/unimplementedFeatures.txt +++ b/unimplementedFeatures.txt @@ -33,6 +33,7 @@ byte and word swap bits Fixed: +PCTLR, can divide CPU speed by 1<->31 Palm OS usage of the "rte" instruction is incompatible with the 68020, switch to 68000 core System Control Register, 0xXXFFF000 all upper banks are registers mode Port D keyboard enable register