2012-05-22 12:10:00 +00:00
|
|
|
#ifdef EPSONRTC_CPP
|
2012-05-21 10:56:48 +00:00
|
|
|
|
2012-05-22 12:10:00 +00:00
|
|
|
void EpsonRTC::rtc_reset() {
|
2012-05-21 10:56:48 +00:00
|
|
|
state = State::Mode;
|
|
|
|
offset = 0;
|
|
|
|
|
2012-05-23 11:27:45 +00:00
|
|
|
resync = 0;
|
2012-05-21 10:56:48 +00:00
|
|
|
pause = 0;
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:10:00 +00:00
|
|
|
uint4 EpsonRTC::rtc_read(uint4 addr) {
|
Update to v089r06 release.
[Yes, the release number is re-used. -Ed.]
byuu says:
I had some bugs in r07 that I couldn't track down, DKJM2's clock was
getting all out of sync.
So I just reverted to r05, blew away both RTCs entirely, and wrote them
cleanly from scratch (obviously looking off the old code.) A bit
extreme, but it worked.
I believe I found the error in the process, day and month were resetting
the counter to 0 instead of 1, it wasn't handling leap year, etc.
While I was at it, I fixed the day-of-week calculation. The SharpRTC
epoch is actually 1000-01-01, and not 1900-01-01.
I'm sure you guys will be really happy that if it ever becomes 1000AD
again and you're playing a ROM hack that uses the SharpRTC and relies on
its weekday value that it will show the correct day now ...
Kind of a pain to compute, but nothing compared to the seventh circle of
hell that was my IBM dBase III Julian<>Gregorian conversion functions :/
Also found a few bugs in the Epson code this way. And I moved the round
seconds actions and flag clear to +125us after flag set.
So, if you had the old r06 or r07, please delete those.
Unfortunately, this took all of my energy today, so the file names
inside manifest changes will have to be in the next WIP.
EDIT: ran a diff against old r07 and new r06.
- added if(days == 31) case twice in EpsonRTC::tick_day()
- forgot weekday = 0; in SharpRTC::load()
- need to move the cartridge+cheat objects up in sfc/Makefile again
- System::init() needs assert(interface != nullptr /* not 0 */)
2012-05-24 23:26:06 +00:00
|
|
|
switch(addr) { default:
|
2012-05-21 10:56:48 +00:00
|
|
|
case 0: return secondlo;
|
|
|
|
case 1: return secondhi | batteryfailure << 3;
|
|
|
|
case 2: return minutelo;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 3: return minutehi | resync << 3;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 4: return hourlo;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 5: return hourhi | meridian << 2 | resync << 3;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 6: return daylo;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 7: return dayhi | dayram << 2 | resync << 3;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 8: return monthlo;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 9: return monthhi | monthram << 1 | resync << 3;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 10: return yearlo;
|
|
|
|
case 11: return yearhi;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 12: return weekday | resync << 3;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 13: {
|
2012-05-22 12:10:00 +00:00
|
|
|
uint1 readflag = irqflag & !irqmask;
|
2012-05-21 10:56:48 +00:00
|
|
|
irqflag = 0;
|
|
|
|
return hold | calendar << 1 | readflag << 2 | roundseconds << 3;
|
|
|
|
}
|
|
|
|
case 14: return irqmask | irqduty << 1 | irqperiod << 2;
|
|
|
|
case 15: return pause | stop << 1 | atime << 2 | test << 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:10:00 +00:00
|
|
|
void EpsonRTC::rtc_write(uint4 addr, uint4 data) {
|
2012-05-21 10:56:48 +00:00
|
|
|
switch(addr) {
|
|
|
|
case 0:
|
|
|
|
secondlo = data;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
secondhi = data;
|
|
|
|
batteryfailure = data >> 3;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
minutelo = data;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
minutehi = data;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
hourlo = data;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
hourhi = data;
|
|
|
|
meridian = data >> 2;
|
|
|
|
if(atime == 1) meridian = 0;
|
|
|
|
if(atime == 0) hourhi &= 1;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
daylo = data;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
dayhi = data;
|
|
|
|
dayram = data >> 2;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
monthlo = data;
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
monthhi = data;
|
|
|
|
monthram = data >> 1;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
yearlo = data;
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
yearhi = data;
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
weekday = data;
|
|
|
|
break;
|
2012-05-23 11:27:45 +00:00
|
|
|
case 13: {
|
|
|
|
bool held = hold;
|
2012-05-21 10:56:48 +00:00
|
|
|
hold = data;
|
|
|
|
calendar = data >> 1;
|
|
|
|
roundseconds = data >> 3;
|
Update to v089r06 release.
[Yes, the release number is re-used. -Ed.]
byuu says:
I had some bugs in r07 that I couldn't track down, DKJM2's clock was
getting all out of sync.
So I just reverted to r05, blew away both RTCs entirely, and wrote them
cleanly from scratch (obviously looking off the old code.) A bit
extreme, but it worked.
I believe I found the error in the process, day and month were resetting
the counter to 0 instead of 1, it wasn't handling leap year, etc.
While I was at it, I fixed the day-of-week calculation. The SharpRTC
epoch is actually 1000-01-01, and not 1900-01-01.
I'm sure you guys will be really happy that if it ever becomes 1000AD
again and you're playing a ROM hack that uses the SharpRTC and relies on
its weekday value that it will show the correct day now ...
Kind of a pain to compute, but nothing compared to the seventh circle of
hell that was my IBM dBase III Julian<>Gregorian conversion functions :/
Also found a few bugs in the Epson code this way. And I moved the round
seconds actions and flag clear to +125us after flag set.
So, if you had the old r06 or r07, please delete those.
Unfortunately, this took all of my energy today, so the file names
inside manifest changes will have to be in the next WIP.
EDIT: ran a diff against old r07 and new r06.
- added if(days == 31) case twice in EpsonRTC::tick_day()
- forgot weekday = 0; in SharpRTC::load()
- need to move the cartridge+cheat objects up in sfc/Makefile again
- System::init() needs assert(interface != nullptr /* not 0 */)
2012-05-24 23:26:06 +00:00
|
|
|
if(held == 1 && hold == 0 && holdtick == 1) {
|
|
|
|
//if a second has passed during hold, increment one second upon resuming
|
|
|
|
holdtick = 0;
|
2012-05-23 11:27:45 +00:00
|
|
|
tick_second();
|
|
|
|
}
|
|
|
|
} break;
|
2012-05-21 10:56:48 +00:00
|
|
|
case 14:
|
|
|
|
irqmask = data;
|
|
|
|
irqduty = data >> 1;
|
|
|
|
irqperiod = data >> 2;
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
pause = data;
|
|
|
|
stop = data >> 1;
|
|
|
|
atime = data >> 2;
|
|
|
|
test = data >> 3;
|
|
|
|
if(atime == 1) meridian = 0;
|
|
|
|
if(atime == 0) hourhi &= 1;
|
2012-05-22 12:10:00 +00:00
|
|
|
if(pause) {
|
|
|
|
secondlo = 0;
|
|
|
|
secondhi = 0;
|
|
|
|
}
|
2012-05-21 10:56:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void EpsonRTC::load(const uint8* data) {
|
2012-05-23 11:27:45 +00:00
|
|
|
secondlo = data[0] >> 0;
|
|
|
|
secondhi = data[0] >> 4;
|
|
|
|
batteryfailure = data[0] >> 7;
|
|
|
|
|
|
|
|
minutelo = data[1] >> 0;
|
|
|
|
minutehi = data[1] >> 4;
|
|
|
|
resync = data[1] >> 7;
|
|
|
|
|
|
|
|
hourlo = data[2] >> 0;
|
|
|
|
hourhi = data[2] >> 4;
|
|
|
|
meridian = data[2] >> 6;
|
|
|
|
|
|
|
|
daylo = data[3] >> 0;
|
|
|
|
dayhi = data[3] >> 4;
|
|
|
|
dayram = data[3] >> 6;
|
|
|
|
|
|
|
|
monthlo = data[4] >> 0;
|
|
|
|
monthhi = data[4] >> 4;
|
|
|
|
monthram = data[4] >> 5;
|
|
|
|
|
|
|
|
yearlo = data[5] >> 0;
|
|
|
|
yearhi = data[5] >> 4;
|
|
|
|
|
|
|
|
weekday = data[6] >> 0;
|
|
|
|
|
|
|
|
hold = data[6] >> 4;
|
|
|
|
calendar = data[6] >> 5;
|
|
|
|
irqflag = data[6] >> 6;
|
|
|
|
roundseconds = data[6] >> 7;
|
|
|
|
|
|
|
|
irqmask = data[7] >> 0;
|
|
|
|
irqduty = data[7] >> 1;
|
|
|
|
irqperiod = data[7] >> 2;
|
|
|
|
|
|
|
|
pause = data[7] >> 4;
|
|
|
|
stop = data[7] >> 5;
|
|
|
|
atime = data[7] >> 6;
|
|
|
|
test = data[7] >> 7;
|
2012-05-21 10:56:48 +00:00
|
|
|
|
|
|
|
uint64 timestamp = 0;
|
|
|
|
for(unsigned byte = 0; byte < 8; byte++) {
|
|
|
|
timestamp |= data[8 + byte] << (byte * 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 diff = (uint64)time(0) - timestamp;
|
|
|
|
while(diff >= 60 * 60 * 24) { tick_day(); diff -= 60 * 60 * 24; }
|
|
|
|
while(diff >= 60 * 60) { tick_hour(); diff -= 60 * 60; }
|
|
|
|
while(diff >= 60) { tick_minute(); diff -= 60; }
|
|
|
|
while(diff--) tick_second();
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void EpsonRTC::save(uint8* data) {
|
2012-05-23 11:27:45 +00:00
|
|
|
data[0] = secondlo << 0 | secondhi << 4 | batteryfailure << 7;
|
|
|
|
data[1] = minutelo << 0 | minutehi << 4 | resync << 7;
|
2012-05-26 08:18:42 +00:00
|
|
|
data[2] = hourlo << 0 | hourhi << 4 | meridian << 6 | resync << 7;
|
|
|
|
data[3] = daylo << 0 | dayhi << 4 | dayram << 6 | resync << 7;
|
|
|
|
data[4] = monthlo << 0 | monthhi << 4 | monthram << 5 | resync << 7;
|
2012-05-23 11:27:45 +00:00
|
|
|
data[5] = yearlo << 0 | yearhi << 4;
|
2012-05-26 08:18:42 +00:00
|
|
|
data[6] = weekday << 0 | resync << 3 | hold << 4 | calendar << 5 | irqflag << 6 | roundseconds << 7;
|
2012-05-23 11:27:45 +00:00
|
|
|
data[7] = irqmask << 0 | irqduty << 1 | irqperiod << 2 | pause << 4 | stop << 5 | atime << 6 | test << 7;
|
2012-05-21 10:56:48 +00:00
|
|
|
|
|
|
|
uint64 timestamp = (uint64)time(0);
|
|
|
|
for(unsigned byte = 0; byte < 8; byte++) {
|
|
|
|
data[8 + byte] = timestamp;
|
|
|
|
timestamp >>= 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|