Add timer status lock logic

This commit is contained in:
meepingsnesroms
2018-04-29 21:29:13 -07:00
parent 9f5c8403d9
commit 3a43cbad4b
5 changed files with 54 additions and 27 deletions

View File

@@ -333,6 +333,7 @@ uint32_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(uint16_t) * 2;//timerStatusReadAcknowledge
size += sizeof(uint8_t) * 2;//ads7846
size += sizeof(uint16_t);//ads7846
size += sizeof(uint8_t) * 7;//palmMisc
@@ -432,10 +433,14 @@ void emulatorSaveState(uint8_t* data){
offset += sizeof(int32_t);
writeStateValueUint32(data + offset, clk32Counter);
offset += sizeof(uint32_t);
writeStateValueDouble(data + offset, timer1CycleCounter);
writeStateValueDouble(data + offset, timerCycleCounter[0]);
offset += sizeof(uint64_t);
writeStateValueDouble(data + offset, timer2CycleCounter);
writeStateValueDouble(data + offset, timerCycleCounter[1]);
offset += sizeof(uint64_t);
writeStateValueUint16(data + offset, timerStatusReadAcknowledge[0]);
offset += sizeof(uint16_t);
writeStateValueUint16(data + offset, timerStatusReadAcknowledge[1]);
offset += sizeof(uint16_t);
//ADS7846
writeStateValueUint8(data + offset, ads7846InputBitsLeft);
@@ -553,10 +558,14 @@ void emulatorLoadState(uint8_t* data){
offset += sizeof(int32_t);
clk32Counter = readStateValueUint32(data + offset);
offset += sizeof(uint32_t);
timer1CycleCounter = readStateValueDouble(data + offset);
timerCycleCounter[0] = readStateValueDouble(data + offset);
offset += sizeof(uint64_t);
timer2CycleCounter = readStateValueDouble(data + offset);
timerCycleCounter[1] = readStateValueDouble(data + offset);
offset += sizeof(uint64_t);
timerStatusReadAcknowledge[0] = readStateValueUint16(data + offset);
offset += sizeof(uint16_t);
timerStatusReadAcknowledge[1] = readStateValueUint16(data + offset);
offset += sizeof(uint16_t);
//ADS7846
ads7846InputBitsLeft = readStateValueUint8(data + offset);

View File

@@ -15,8 +15,8 @@
chip_t chips[CHIP_END];
int32_t pllWakeWait;
uint32_t clk32Counter;
double timer1CycleCounter;
double timer2CycleCounter;
double timerCycleCounter[2];
uint16_t timerStatusReadAcknowledge[2];
bool pllIsOn();
@@ -435,6 +435,14 @@ unsigned int getHwRegister16(unsigned int address){
printUnknownHwAccess(address, 0, 16, false);
#endif
switch(address){
case TSTAT1:
timerStatusReadAcknowledge[0] = registerArrayRead16(TSTAT1);//active bits acknowledged
return registerArrayRead16(TSTAT1);
case TSTAT2:
timerStatusReadAcknowledge[1] = registerArrayRead16(TSTAT2);//active bits acknowledged
return registerArrayRead16(TSTAT2);
//32 bit registers accessed as 16 bit
case IMR:
@@ -466,8 +474,6 @@ unsigned int getHwRegister16(unsigned int address){
case TCMP2:
case TPRER1:
case TPRER2:
case TSTAT1:
case TSTAT2:
case SPICONT2:
case SPIDATA2:
//simple read, no actions needed
@@ -819,12 +825,20 @@ void setHwRegister16(unsigned int address, unsigned int value){
setSpiCont2(value);
break;
case TSTAT1:
//preserve any unread bits
registerArrayWrite16(TSTAT1, (value & timerStatusReadAcknowledge[0]) | (registerArrayRead16(TSTAT1) & ~timerStatusReadAcknowledge[0]));
break;
case TSTAT2:
//preserve any unread bits
registerArrayWrite16(TSTAT2, (value & timerStatusReadAcknowledge[1]) | (registerArrayRead16(TSTAT2) & ~timerStatusReadAcknowledge[1]));
break;
case TCMP1:
case TCMP2:
case TPRER1:
case TPRER2:
case TSTAT1:
case TSTAT2:
case SPIDATA2:
//simple write, no actions needed
registerArrayWrite16(address, value);
@@ -891,8 +905,10 @@ void resetHwRegisters(){
memset(palmReg, 0x00, REG_SIZE - BOOTLOADER_SIZE);
clk32Counter = 0;
pllWakeWait = -1;
timer1CycleCounter = 0.0;
timer2CycleCounter = 0.0;
timerCycleCounter[0] = 0.0;
timerCycleCounter[1] = 0.0;
timerStatusReadAcknowledge[0] = 0x0000;
timerStatusReadAcknowledge[1] = 0x0000;
for(uint8_t chip = CHIP_BEGIN; chip < CHIP_END; chip++){
chips[chip].enable = false;
chips[chip].start = 0x00000000;

View File

@@ -58,8 +58,8 @@ typedef struct{
extern chip_t chips[];
extern int32_t pllWakeWait;
extern uint32_t clk32Counter;
extern double timer1CycleCounter;
extern double timer2CycleCounter;
extern double timerCycleCounter[];
extern uint16_t timerStatusReadAcknowledge[];
//memory accessors
unsigned int getHwRegister8(unsigned int address);

View File

@@ -114,22 +114,22 @@ static inline void timer12Clk32(){
case 0x0001://SYSCLK / timer prescaler
if(pllIsOn())
timer1CycleCounter += sysclksPerClk32() / timer1Prescaler;
timerCycleCounter[0] += sysclksPerClk32() / timer1Prescaler;
break;
case 0x0002://SYSCLK / 16 / timer prescaler
if(pllIsOn())
timer1CycleCounter += sysclksPerClk32() / 16.0 / timer1Prescaler;
timerCycleCounter[0] += sysclksPerClk32() / 16.0 / timer1Prescaler;
break;
default://CLK32 / timer prescaler
timer1CycleCounter += 1.0 / timer1Prescaler;
timerCycleCounter[0] += 1.0 / timer1Prescaler;
break;
}
if(timer1CycleCounter >= 1.0){
timer1Count += (uint16_t)timer1CycleCounter;
timer1CycleCounter -= (uint16_t)timer1CycleCounter;
if(timerCycleCounter[0] >= 1.0){
timer1Count += (uint16_t)timerCycleCounter[0];
timerCycleCounter[0] -= (uint16_t)timerCycleCounter[0];
}
if(timer1OldCount < timer1Compare && timer1Count >= timer1Compare){
@@ -141,6 +141,7 @@ static inline void timer12Clk32(){
//set timer triggered bit
registerArrayWrite16(TSTAT1, registerArrayRead16(TSTAT1) | 0x0001);
timerStatusReadAcknowledge[0] &= 0xFFFE;//lock bit until next read
if(!(timer1Control & 0x0100)){
//not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare
@@ -163,22 +164,22 @@ static inline void timer12Clk32(){
case 0x0001://SYSCLK / timer prescaler
if(pllIsOn())
timer2CycleCounter += sysclksPerClk32() / timer2Prescaler;
timerCycleCounter[1] += sysclksPerClk32() / timer2Prescaler;
break;
case 0x0002://SYSCLK / 16 / timer prescaler
if(pllIsOn())
timer2CycleCounter += sysclksPerClk32() / 16.0 / timer2Prescaler;
timerCycleCounter[1] += sysclksPerClk32() / 16.0 / timer2Prescaler;
break;
default://CLK32 / timer prescaler
timer2CycleCounter += 1.0 / timer2Prescaler;
timerCycleCounter[1] += 1.0 / timer2Prescaler;
break;
}
if(timer2CycleCounter >= 1.0){
timer2Count += (uint16_t)timer2CycleCounter;
timer2CycleCounter -= (uint16_t)timer2CycleCounter;
if(timerCycleCounter[1] >= 1.0){
timer2Count += (uint16_t)timerCycleCounter[1];
timerCycleCounter[1] -= (uint16_t)timerCycleCounter[1];
}
if(timer2OldCount < timer2Compare && timer2Count >= timer2Compare){
@@ -190,6 +191,7 @@ static inline void timer12Clk32(){
//set timer triggered bit
registerArrayWrite16(TSTAT2, registerArrayRead16(TSTAT2) | 0x0001);
timerStatusReadAcknowledge[1] &= 0xFFFE;//lock bit until next read
if(!(timer2Control & 0x0100)){
//not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare

View File

@@ -21,7 +21,6 @@ interrupt control register (ICR), POL5 and edge trigger selects
ADC7846 temperature sensors
ADC7846 dock sensor
some undocumented I/O might be on port e and port j
timers shouldn't allow comp bits to be cleared until read with a 1 in them and should remain in interrupt state until they are cleared(this is unverified)
Debug tools:
missing icons
@@ -41,6 +40,7 @@ Had to modify musashi because the damn NDK isn't C compatible, m68kcpu.h, line 5
Fixed:
timers shouldn't allow comp bits to be cleared until read with a 1 in them and should remain in interrupt state until they are cleared(the interrupt state part is unverified)
SED1376 byte and word swap bits
qt play pause icon not working for emu control button
SED1376 register access