SYSCLKs are now separeate from CLK32

This commit is contained in:
meepingsnesroms
2018-10-11 10:55:47 -07:00
parent 508cab0b41
commit f77344dae2
6 changed files with 170 additions and 307 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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