From f77344dae2b5ec08f9e869ad54eab3e5fa09863a Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Thu, 11 Oct 2018 10:55:47 -0700 Subject: [PATCH] SYSCLKs are now separeate from CLK32 --- src/emulator.c | 15 +- src/emulator.h | 2 +- src/hardwareRegisters.c | 39 +-- src/hardwareRegisters.h | 12 +- src/hardwareRegistersAccessors.c.h | 2 +- src/hardwareRegistersTiming.c.h | 407 ++++++++++------------------- 6 files changed, 170 insertions(+), 307 deletions(-) diff --git a/src/emulator.c b/src/emulator.c index a5e3a26..109d831 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -43,7 +43,7 @@ uint16_t* palmExtendedFramebuffer; int16_t palmAudio[AUDIO_SAMPLES * 2]; uint32_t palmAudioSampleIndex; uint32_t palmSpecialFeatures; -double palmCrystalCycles;//how many cycles before toggling the 32.768 kHz crystal +double palmSysclksPerClk32;//how many SYSCLK cycles before toggling the 32.768 kHz crystal double palmCycleCounter;//can be greater then 0 if too many cycles where run double palmClockMultiplier;//used by the emulator to overclock the emulated Palm @@ -167,6 +167,7 @@ uint64_t emulatorGetStateSize(){ size += sizeof(uint64_t) * 4;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers size += sizeof(int32_t);//pllWakeWait size += sizeof(uint32_t);//clk32Counter + size += sizeof(uint64_t);//pctlrCpuClockDivider size += sizeof(uint16_t) * 2;//timerStatusReadAcknowledge size += sizeof(uint32_t);//interruptEdgeTriggered size += sizeof(uint16_t) * 9;//RX 8 * 16 SPI1 FIFO, 1 index is for FIFO full @@ -247,7 +248,7 @@ bool emulatorSaveState(buffer_t buffer){ } //timing - writeStateValueDouble(buffer.data + offset, palmCrystalCycles); + writeStateValueDouble(buffer.data + offset, palmSysclksPerClk32); offset += sizeof(uint64_t); writeStateValueDouble(buffer.data + offset, palmCycleCounter); offset += sizeof(uint64_t); @@ -255,6 +256,8 @@ bool emulatorSaveState(buffer_t buffer){ offset += sizeof(int32_t); writeStateValueUint32(buffer.data + offset, clk32Counter); offset += sizeof(uint32_t); + writeStateValueDouble(buffer.data + offset, pctlrCpuClockDivider); + offset += sizeof(uint64_t); writeStateValueDouble(buffer.data + offset, timerCycleCounter[0]); offset += sizeof(uint64_t); writeStateValueDouble(buffer.data + offset, timerCycleCounter[1]); @@ -392,7 +395,7 @@ bool emulatorLoadState(buffer_t buffer){ } //timing - palmCrystalCycles = readStateValueDouble(buffer.data + offset); + palmSysclksPerClk32 = readStateValueDouble(buffer.data + offset); offset += sizeof(uint64_t); palmCycleCounter = readStateValueDouble(buffer.data + offset); offset += sizeof(uint64_t); @@ -400,6 +403,8 @@ bool emulatorLoadState(buffer_t buffer){ offset += sizeof(int32_t); clk32Counter = readStateValueUint32(buffer.data + offset); offset += sizeof(uint32_t); + pctlrCpuClockDivider = readStateValueDouble(buffer.data + offset); + offset += sizeof(uint64_t); timerCycleCounter[0] = readStateValueDouble(buffer.data + offset); offset += sizeof(uint64_t); timerCycleCounter[1] = readStateValueDouble(buffer.data + offset); @@ -525,8 +530,8 @@ void emulateFrame(){ palmAudioSampleIndex = 0; while(palmCycleCounter < (double)CRYSTAL_FREQUENCY / EMU_FPS){ - if(palmCrystalCycles > 0.0) - m68k_execute(palmCrystalCycles * palmClockMultiplier); + m68k_execute(palmSysclksPerClk32 * pctlrCpuClockDivider * palmClockMultiplier); + sysclks(palmSysclksPerClk32); clk32(); palmCycleCounter += 1.0; } diff --git a/src/emulator.h b/src/emulator.h index 0acde66..114358c 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -132,7 +132,7 @@ extern uint16_t* palmExtendedFramebuffer;//read allowed if FEATURE_320x320 is on extern int16_t palmAudio[];//read allowed, 2 channel signed 16 bit audio extern uint32_t palmAudioSampleIndex;//dont touch extern uint32_t palmSpecialFeatures;//read allowed -extern double palmCrystalCycles;//dont touch +extern double palmSysclksPerClk32;//dont touch extern double palmCycleCounter;//dont touch extern double palmClockMultiplier;//read/write allowed diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index b8ab333..9044124 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -18,6 +18,7 @@ chip_t chips[CHIP_END]; int32_t pllWakeWait; uint32_t clk32Counter; +double pctlrCpuClockDivider; double timerCycleCounter[2]; uint16_t timerStatusReadAcknowledge[2]; uint32_t interruptEdgeTriggered; @@ -35,8 +36,8 @@ uint8_t pwm1WritePosition; static void checkInterrupts(); static void checkPortDInterrupts(); -static void recalculateCpuSpeed(); static void pllWakeCpuIfOff(); +static double sysclksPerClk32(); #include "hardwareRegistersAccessors.c.h" #include "hardwareRegistersTiming.c.h" @@ -112,30 +113,6 @@ void setWriteProtectViolation(uint32_t address){ m68328BusError(address, true); } -static void recalculateCpuSpeed(){ - double newCpuSpeed = sysclksPerClk32(); - uint8_t pctlr = registerArrayRead8(PCTLR); - - //power control burst mode - if(pctlr & 0x80) - newCpuSpeed *= (pctlr & 0x1F) / 31.0; - - /* - if(newCpuSpeed != palmCrystalCycles){ - debugLog("New CPU frequency of:%f cycles per second.\n", newCpuSpeed * CRYSTAL_FREQUENCY); - debugLog("New CLK32 cycle count of:%f.\n", newCpuSpeed); - if(newCpuSpeed == 0.0){ - if(pllIsOn()) - debugLog("CPU turned off with PCTLR.\n"); - else - debugLog("CPU turned off with DISPLL bit.\n"); - } - } - */ - - palmCrystalCycles = newCpuSpeed; -} - static void pllWakeCpuIfOff(){ if(!pllIsOn() && pllWakeWait == -1){ //PLL is off and not already in the process of waking up @@ -214,7 +191,7 @@ static void checkInterrupts(){ //even masked interrupts turn off PCTLR, Chapter 4.5.4 MC68VZ328UM.pdf if(intLevel > 0 && registerArrayRead8(PCTLR) & 0x80){ registerArrayWrite8(PCTLR, registerArrayRead8(PCTLR) & 0x1F); - recalculateCpuSpeed(); + pctlrCpuClockDivider = 1.0; } m68k_set_irq(intLevel);//should be called even if intLevel is 0, that is how the interrupt state gets cleared @@ -647,7 +624,8 @@ void setHwRegister8(uint32_t address, uint8_t value){ case PCTLR: registerArrayWrite8(address, value & 0x9F); - recalculateCpuSpeed(); + if(value & 0x80) + pctlrCpuClockDivider = (value & 0x1F) / 31.0; break; case IVR: @@ -836,7 +814,7 @@ void setHwRegister16(uint32_t address, uint16_t value){ case PLLCR: //CLKEN is required for SED1376 operation registerArrayWrite16(PLLCR, value & 0x3FBB); - recalculateCpuSpeed(); + palmSysclksPerClk32 = sysclksPerClk32(); setSed1376Attached(sed1376ClockConnected()); if(value & 0x0008){ @@ -1090,8 +1068,9 @@ void resetHwRegisters(){ uint16_t oldDayr = registerArrayRead16(DAYR);//preserve DAYR memset(palmReg, 0x00, REG_SIZE - BOOTLOADER_SIZE); - palmCrystalCycles = 0.0; + palmSysclksPerClk32 = 0.0; clk32Counter = 0; + pctlrCpuClockDivider = 1.0; pllWakeWait = -1; timerCycleCounter[0] = 0.0; timerCycleCounter[1] = 0.0; @@ -1230,7 +1209,7 @@ void resetHwRegisters(){ updateAds7846ChipSelectStatus(); updateBacklightAmplifierStatus(); - recalculateCpuSpeed(); + palmSysclksPerClk32 = sysclksPerClk32(); } void setRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds){ diff --git a/src/hardwareRegisters.h b/src/hardwareRegisters.h index 0dd4252..41791a1 100644 --- a/src/hardwareRegisters.h +++ b/src/hardwareRegisters.h @@ -28,11 +28,9 @@ #define INT_SPI2 0x00000001//level 4 //reasons a timer is triggered -#define TIMER_REASON_STOP 0x0000 -#define TIMER_REASON_SYSCLK 0x0001 -#define TIMER_REASON_SYSCLK16 0x0002 -#define TIMER_REASON_TIN 0x0003 -#define TIMER_REASON_CLK32 0x0004 +#define TIMER_REASON_SYSCLK 0x0000 +#define TIMER_REASON_TIN 0x0001 +#define TIMER_REASON_CLK32 0x0002 //chip names enum{ @@ -67,6 +65,7 @@ typedef struct{ extern chip_t chips[]; extern int32_t pllWakeWait; extern uint32_t clk32Counter; +extern double pctlrCpuClockDivider; extern double timerCycleCounter[]; extern uint16_t timerStatusReadAcknowledge[]; extern uint32_t interruptEdgeTriggered; @@ -82,7 +81,8 @@ extern uint8_t pwm1ReadPosition; extern uint8_t pwm1WritePosition; //timing -void clk32();//also checks all interrupts +void clk32(); +void sysclks(double value); //CPU bool pllIsOn(); diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 6d81f05..ab0fd58 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -230,7 +230,7 @@ static inline void setPllfsr(uint16_t value){ if(!(oldPllfsr & 0x4000)){ //frequency protect bit not set registerArrayWrite16(PLLFSR, (value & 0x4FFF) | (oldPllfsr & 0x8000));//preserve CLK32 bit - recalculateCpuSpeed(); + palmSysclksPerClk32 = sysclksPerClk32(); } } diff --git a/src/hardwareRegistersTiming.c.h b/src/hardwareRegistersTiming.c.h index 0e0a297..69a5555 100644 --- a/src/hardwareRegistersTiming.c.h +++ b/src/hardwareRegistersTiming.c.h @@ -1,7 +1,139 @@ static void timer1(uint8_t reason, double sysclks); -static void timer2(uint8_t reason, double sysclks) +static void timer2(uint8_t reason, double sysclks); -static inline double dmaclksPerClk32(){ +static void timer1(uint8_t reason, double sysclks){ + uint16_t timer1Control = registerArrayRead16(TCTL1); + uint16_t timer1Compare = registerArrayRead16(TCMP1); + double timer1OldCount = timerCycleCounter[0]; + double timer1Prescaler = (registerArrayRead16(TPRER1) & 0x00FF) + 1; + bool timer1Enabled = timer1Control & 0x0001; + + if(timer1Enabled){ + switch((timer1Control & 0x000E) >> 1){ + case 0x0000://stop counter + //do nothing + return; + + case 0x0001://SYSCLK / timer prescaler + if(reason != TIMER_REASON_SYSCLK) + return; + timerCycleCounter[0] += sysclks / timer1Prescaler; + break; + + case 0x0002://SYSCLK / 16 / timer prescaler + if(reason != TIMER_REASON_SYSCLK) + return; + timerCycleCounter[0] += sysclks / 16.0 / timer1Prescaler; + break; + + case 0x0003://TIN/TOUT pin / timer prescaler, the other timer can be attached to TIN/TOUT + if(reason != TIMER_REASON_TIN) + return; + timerCycleCounter[0] += 1.0 / timer1Prescaler; + break; + + default://CLK32 / timer prescaler + if(reason != TIMER_REASON_CLK32) + return; + timerCycleCounter[0] += 1.0 / timer1Prescaler; + break; + } + + if(timer1OldCount < timer1Compare && timerCycleCounter[0] >= timer1Compare){ + //the comparison against the old value is to prevent an interrupt on every increment in free running mode + //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time + uint8_t pcrTinToutConfig = registerArrayRead8(PCR) & 0x03;//TIN/TOUT seems not to be physicaly connected but cascaded timers still need to be supported + + //interrupt enabled + if(timer1Control & 0x0010) + setIprIsrBit(INT_TMR1); + + //set timer triggered bit + registerArrayWrite16(TSTAT1, registerArrayRead16(TSTAT1) | 0x0001); + timerStatusReadAcknowledge[0] &= 0xFFFE;//lock bit until next read + + //increment other timer if enabled + if(pcrTinToutConfig == 0x03) + timer2(TIMER_REASON_TIN, 0); + + //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare + if(!(timer1Control & 0x0100)) + timerCycleCounter[0] -= timer1Compare; + } + + if(timerCycleCounter[0] > 0xFFFF) + timerCycleCounter[0] -= 0xFFFF; + registerArrayWrite16(TCN1, (uint16_t)timerCycleCounter[0]); + } +} + +static void timer2(uint8_t reason, double sysclks){ + uint16_t timer2Control = registerArrayRead16(TCTL2); + uint16_t timer2Compare = registerArrayRead16(TCMP2); + double timer2OldCount = timerCycleCounter[1]; + double timer2Prescaler = (registerArrayRead16(TPRER2) & 0x00FF) + 1; + bool timer2Enabled = timer2Control & 0x0001; + + if(timer2Enabled){ + switch((timer2Control & 0x000E) >> 1){ + case 0x0000://stop counter + //do nothing + return; + + case 0x0001://SYSCLK / timer prescaler + if(reason != TIMER_REASON_SYSCLK) + return; + timerCycleCounter[1] += sysclks / timer2Prescaler; + break; + + case 0x0002://SYSCLK / 16 / timer prescaler + if(reason != TIMER_REASON_SYSCLK) + return; + timerCycleCounter[1] += sysclks / 16.0 / timer2Prescaler; + break; + + case 0x0003://TIN/TOUT pin / timer prescaler, the other timer can be attached to TIN/TOUT + if(reason != TIMER_REASON_TIN) + return; + timerCycleCounter[1] += 1.0 / timer2Prescaler; + break; + + default://CLK32 / timer prescaler + if(reason != TIMER_REASON_CLK32) + return; + timerCycleCounter[1] += 1.0 / timer2Prescaler; + break; + } + + if(timer2OldCount < timer2Compare && timerCycleCounter[1] >= timer2Compare){ + //the comparison against the old value is to prevent an interrupt on every increment in free running mode + //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time + uint8_t pcrTinToutConfig = registerArrayRead8(PCR) & 0x03;//TIN/TOUT seems not to be physicaly connected but cascaded timers still need to be supported + + //interrupt enabled + if(timer2Control & 0x0010) + setIprIsrBit(INT_TMR2); + + //set timer triggered bit + registerArrayWrite16(TSTAT2, registerArrayRead16(TSTAT2) | 0x0001); + timerStatusReadAcknowledge[1] &= 0xFFFE;//lock bit until next read + + //increment other timer if enabled + if(pcrTinToutConfig == 0x02) + timer1(TIMER_REASON_TIN, 0); + + //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare + if(!(timer2Control & 0x0100)) + timerCycleCounter[1] -= timer2Compare; + } + + if(timerCycleCounter[1] > 0xFFFF) + timerCycleCounter[1] -= 0xFFFF; + registerArrayWrite16(TCN2, (uint16_t)timerCycleCounter[1]); + } +} + +static double dmaclksPerClk32(){ double dmaclks; if(pllIsOn()){ @@ -26,7 +158,7 @@ static inline double dmaclksPerClk32(){ return dmaclks; } -static inline double sysclksPerClk32(){ +static double sysclksPerClk32(){ uint8_t sysclkSelect = registerArrayRead16(PLLCR) >> 8 & 0x0003; //> 4 means run at full speed, no divider @@ -81,265 +213,6 @@ static inline void rtiInterruptClk32(){ } } -static void timer1(uint8_t reason, double sysclks){ - uint16_t timer1Control = registerArrayRead16(TCTL1); - uint16_t timer1Compare = registerArrayRead16(TCMP1); - double timer1OldCount = timerCycleCounter[0]; - double timer1Prescaler = (registerArrayRead16(TPRER1) & 0x00FF) + 1; - bool timer1Enabled = timer1Control & 0x0001; - - if(timer1Enabled){ - uint8_t timer1Source = (timer1Control & 0x000E) >> 1; - - //all CLK32 modes compare to 0x0004 - if(timer1Source > 0x0004) - timer1Source = TIMER_REASON_CLK32; - - if(timer1Source != reason) - return; - - switch(timer1Source){ - case TIMER_REASON_STOP://stop counter - //do nothing - return; - - case TIMER_REASON_SYSCLK://SYSCLK / timer prescaler - timerCycleCounter[0] += sysclks / timer1Prescaler; - break; - - case TIMER_REASON_SYSCLK16://SYSCLK / 16 / timer prescaler - timerCycleCounter[0] += sysclks / 16.0 / timer1Prescaler; - break; - - case TIMER_REASON_TIN://TIN/TOUT pin / timer prescaler, the other timer can be attached to TIN/TOUT - case TIMER_REASON_CLK32://CLK32 / timer prescaler - timerCycleCounter[0] += 1.0 / timer1Prescaler; - break; - } - - if(timer1OldCount < timer1Compare && timerCycleCounter[0] >= timer1Compare){ - //the comparison against the old value is to prevent an interrupt on every increment in free running mode - //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time - uint8_t pcrTinToutConfig = registerArrayRead8(PCR) & 0x03;//TIN/TOUT seems not to be physicaly connected but cascaded timers still need to be supported - - //interrupt enabled - if(timer1Control & 0x0010) - setIprIsrBit(INT_TMR1); - - //set timer triggered bit - registerArrayWrite16(TSTAT1, registerArrayRead16(TSTAT1) | 0x0001); - timerStatusReadAcknowledge[0] &= 0xFFFE;//lock bit until next read - - if(pcrTinToutConfig == 0x03) - timer2(TIMER_REASON_TIN, 0); - - //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare - if(!(timer1Control & 0x0100)) - timerCycleCounter[0] -= timer1Compare; - } - - if(timerCycleCounter[0] > 0xFFFF) - timerCycleCounter[0] -= 0xFFFF; - registerArrayWrite16(TCN1, (uint16_t)timerCycleCounter[0]); - } -} - -static void timer2(uint8_t reason, double sysclks){ - uint16_t timer2Control = registerArrayRead16(TCTL2); - uint16_t timer2Compare = registerArrayRead16(TCMP2); - double timer2OldCount = timerCycleCounter[1]; - double timer2Prescaler = (registerArrayRead16(TPRER2) & 0x00FF) + 1; - bool timer2Enabled = timer2Control & 0x0001; - - if(timer2Enabled){ - uint8_t timer2Source = (timer2Control & 0x000E) >> 1; - - //all CLK32 modes compare to 0x0004 - if(timer2Source > 0x0004) - timer2Source = 0x0004; - - if(timer2Source != reason) - return; - - switch(timer2Source){ - case TIMER_REASON_STOP://stop counter - //do nothing - return; - - case TIMER_REASON_SYSCLK://SYSCLK / timer prescaler - timerCycleCounter[1] += sysclks / timer2Prescaler; - break; - - case TIMER_REASON_SYSCLK16://SYSCLK / 16 / timer prescaler - timerCycleCounter[1] += sysclks / 16.0 / timer2Prescaler; - break; - - case TIMER_REASON_TIN://TIN/TOUT pin / timer prescaler, the other timer can be attached to TIN/TOUT - case TIMER_REASON_CLK32://CLK32 / timer prescaler - timerCycleCounter[1] += 1.0 / timer2Prescaler; - break; - } - - if(timer2OldCount < timer2Compare && timerCycleCounter[1] >= timer2Compare){ - //the comparison against the old value is to prevent an interrupt on every increment in free running mode - //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time - uint8_t pcrTinToutConfig = registerArrayRead8(PCR) & 0x03;//TIN/TOUT seems not to be physicaly connected but cascaded timers still need to be supported - - //interrupt enabled - if(timer2Control & 0x0010) - setIprIsrBit(INT_TMR2); - - //set timer triggered bit - registerArrayWrite16(TSTAT2, registerArrayRead16(TSTAT2) | 0x0001); - timerStatusReadAcknowledge[1] &= 0xFFFE;//lock bit until next read - - if(pcrTinToutConfig == 0x02) - timer1(TIMER_REASON_TIN, 0); - - //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare - if(!(timer2Control & 0x0100)) - timerCycleCounter[1] -= timer2Compare; - } - - if(timerCycleCounter[1] > 0xFFFF) - timerCycleCounter[1] -= 0xFFFF; - registerArrayWrite16(TCN2, (uint16_t)timerCycleCounter[1]); - } -} - -static inline void timer12Clk32(){ - //this function is part of clk32(); - uint16_t timer1Control = registerArrayRead16(TCTL1); - uint16_t timer1Compare = registerArrayRead16(TCMP1); - double timer1OldCount = timerCycleCounter[0]; - double timer1Prescaler = (registerArrayRead16(TPRER1) & 0x00FF) + 1; - bool timer1Enabled = timer1Control & 0x0001; - uint16_t timer2Control = registerArrayRead16(TCTL2); - uint16_t timer2Compare = registerArrayRead16(TCMP2); - double timer2OldCount = timerCycleCounter[0]; - double timer2Prescaler = (registerArrayRead16(TPRER2) & 0x00FF) + 1; - bool timer2Enabled = timer2Control & 0x0001; - uint8_t pcrTinToutConfig = registerArrayRead8(PCR) & 0x03;//TIN/TOUT seems not to be physicaly connected but cascaded timers still need to be supported - double sysclks = sysclksPerClk32(); - - if(timer1Enabled && pcrTinToutConfig != 0x02){ - switch((timer1Control & 0x000E) >> 1){ - case 0x0000://stop counter - //do nothing - break; - - case 0x0001://SYSCLK / timer prescaler - timerCycleCounter[0] += sysclks / timer1Prescaler; - break; - - case 0x0002://SYSCLK / 16 / timer prescaler - timerCycleCounter[0] += sysclks / 16.0 / timer1Prescaler; - break; - - case 0x0003://TIN/TOUT pin / timer prescaler, nothing is attached to TIN/TOUT - //do nothing - break; - - default://CLK32 / timer prescaler - timerCycleCounter[0] += 1.0 / timer1Prescaler; - break; - } - } - - if(timer2Enabled && pcrTinToutConfig != 0x03){ - switch((timer2Control & 0x000E) >> 1){ - case 0x0000://stop counter - //do nothing - break; - - case 0x0001://SYSCLK / timer prescaler - timerCycleCounter[1] += sysclks / timer2Prescaler; - break; - - case 0x0002://SYSCLK / 16 / timer prescaler - timerCycleCounter[1] += sysclks / 16.0 / timer2Prescaler; - break; - - case 0x0003://TIN/TOUT pin / timer prescaler, nothing is attached to TIN/TOUT - //do nothing - break; - - default://CLK32 / timer prescaler - timerCycleCounter[1] += 1.0 / timer2Prescaler; - break; - } - } - - if(timer1Enabled && timer1OldCount < timer1Compare && timerCycleCounter[0] >= timer1Compare){ - //the comparison against the old value is to prevent an interrupt on every increment in free running mode - //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time - - //interrupt enabled - if(timer1Control & 0x0010) - setIprIsrBit(INT_TMR1); - - //set timer triggered bit - registerArrayWrite16(TSTAT1, registerArrayRead16(TSTAT1) | 0x0001); - timerStatusReadAcknowledge[0] &= 0xFFFE;//lock bit until next read - - //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare - if(!(timer1Control & 0x0100)) - timerCycleCounter[0] -= timer1Compare; - } - - if(timer2Enabled && timer2OldCount < timer2Compare && timerCycleCounter[1] >= timer2Compare){ - //the comparison against the old value is to prevent an interrupt on every increment in free running mode - //the timer is not cycle accurate and may not hit the value in the compare register perfectly so check if it would have during in the emulated time - - //interrupt enabled - if(timer2Control & 0x0010) - setIprIsrBit(INT_TMR2); - - //set timer triggered bit - registerArrayWrite16(TSTAT2, registerArrayRead16(TSTAT2) | 0x0001); - timerStatusReadAcknowledge[1] &= 0xFFFE;//lock bit until next read - - //not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare - if(!(timer2Control & 0x0100)) - timerCycleCounter[1] -= timer2Compare; - } - - if(timer1Enabled && timer2Enabled){ - switch(pcrTinToutConfig){ - case 0x00: - case 0x01: - //do nothing - break; - - case 0x02: - //PCR T field, 0x02 = Timer 2 OUT -> Timer 1 IN; TIN -> Timer 2 (DIR6 = 0), or TOUT -> Timer 1 (DIR6 = 1). - if(timerCycleCounter[1] > 0xFFFF) - timerCycleCounter[0] += 1.0; - break; - - case 0x03: - //PCR T field, 0x03 = Timer 1 OUT -> Timer 2 IN; TIN -> Timer 1 (DIR6 = 0), or TOUT -> Timer 2 (DIR6 = 1) - if(timerCycleCounter[0] > 0xFFFF) - timerCycleCounter[1] += 1.0; - break; - } - } - - //if timer chaining causes an interrupt the actual interrupt takes place the next time this function is called - - if(timer1Enabled){ - if(timerCycleCounter[0] > 0xFFFF) - timerCycleCounter[0] -= 0xFFFF; - registerArrayWrite16(TCN1, (uint16_t)timerCycleCounter[0]); - } - - if(timer2Enabled){ - if(timerCycleCounter[1] > 0xFFFF) - timerCycleCounter[1] -= 0xFFFF; - registerArrayWrite16(TCN2, (uint16_t)timerCycleCounter[1]); - } -} - static inline void watchdogSecondTickClk32(){ //this function is part of clk32(); uint16_t watchdogState = registerArrayRead16(WATCHDOG); @@ -447,7 +320,8 @@ void clk32(){ if(registerArrayRead16(RTCCTL) & 0x0080 || registerArrayRead16(WATCHDOG) & 0x01) rtiInterruptClk32(); - timer12Clk32(); + timer1(TIMER_REASON_CLK32, 0); + timer2(TIMER_REASON_CLK32, 0); samplePwmXClk32(); //PLLCR wake select wait @@ -455,7 +329,7 @@ void clk32(){ if(pllWakeWait == 0){ //reenable PLL and CPU registerArrayWrite16(PLLCR, registerArrayRead16(PLLCR) & 0xFFF7); - recalculateCpuSpeed(); + palmSysclksPerClk32 = sysclksPerClk32(); debugLog("PLL reenabled, CPU is on!\n"); } pllWakeWait--; @@ -463,3 +337,8 @@ void clk32(){ checkInterrupts(); } + +void sysclks(double count){ + timer1(TIMER_REASON_SYSCLK, count); + timer2(TIMER_REASON_SYSCLK, count); +}