Add PCTRL register, use specific function to set CPU speed

This commit is contained in:
meepingsnesroms
2018-04-24 15:25:28 -07:00
parent 26259b8ce6
commit 2d39345ad8
6 changed files with 48 additions and 36 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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){

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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