diff --git a/src/emulator.c b/src/emulator.c index fb7f250..096ade6 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -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); diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index 475004a..5f1584c 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -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; diff --git a/src/hardwareRegisters.h b/src/hardwareRegisters.h index 6393581..e269f07 100644 --- a/src/hardwareRegisters.h +++ b/src/hardwareRegisters.h @@ -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); diff --git a/src/hardwareRegistersTiming.c.h b/src/hardwareRegistersTiming.c.h index cfe63ae..7ba5ba5 100644 --- a/src/hardwareRegistersTiming.c.h +++ b/src/hardwareRegistersTiming.c.h @@ -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 diff --git a/unimplementedFeatures.txt b/unimplementedFeatures.txt index 4517066..95dade9 100644 --- a/unimplementedFeatures.txt +++ b/unimplementedFeatures.txt @@ -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