GBA Hardware: Begin fixing RTC implementation

This commit is contained in:
Vicki Pfau 2017-03-19 09:23:54 -07:00
parent 53778e8d92
commit a278899314
2 changed files with 40 additions and 21 deletions

View File

@ -48,24 +48,30 @@ enum GPIODirection {
GPIO_READ_WRITE = 1 GPIO_READ_WRITE = 1
}; };
DECL_BITFIELD(RTCControl, uint32_t); DECL_BITFIELD(RTCControl, uint8_t);
DECL_BIT(RTCControl, MinIRQ, 3); DECL_BIT(RTCControl, Reset, 0);
DECL_BIT(RTCControl, Hour24, 6); DECL_BIT(RTCControl, Hour24, 1);
DECL_BIT(RTCControl, Poweroff, 7); DECL_BIT(RTCControl, IRQ1, 4);
DECL_BIT(RTCControl, IRQ2, 5);
enum RTCCommand { enum RTCCommand {
RTC_RESET = 0, RTC_STATUS1 = 0,
RTC_ALARM1 = 1,
RTC_DATETIME = 2, RTC_DATETIME = 2,
RTC_FORCE_IRQ = 3, RTC_FORCE_IRQ = 3,
RTC_CONTROL = 4, RTC_STATUS2 = 4,
RTC_TIME = 6 RTC_ALARM2 = 5,
RTC_TIME = 6,
RTC_FREE_REG = 7
}; };
DECL_BITFIELD(RTCCommandData, uint32_t); DECL_BITFIELD(RTCCommandData, uint8_t);
DECL_BITS(RTCCommandData, Magic, 0, 4); DECL_BITS(RTCCommandData, Magic, 0, 4);
DECL_BITS(RTCCommandData, Command, 4, 3); DECL_BITS(RTCCommandData, Command, 4, 3);
DECL_BIT(RTCCommandData, Reading, 7); DECL_BIT(RTCCommandData, Reading, 7);
DECL_BITFIELD(RTCStatus2, uint8_t);
#pragma pack(push, 1) #pragma pack(push, 1)
struct GBARTC { struct GBARTC {
int32_t bytesRemaining; int32_t bytesRemaining;
@ -74,7 +80,12 @@ struct GBARTC {
int32_t bits; int32_t bits;
int32_t commandActive; int32_t commandActive;
RTCCommandData command; RTCCommandData command;
RTCStatus2 status2;
uint8_t freeReg;
RTCControl control; RTCControl control;
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint8_t time[7]; uint8_t time[7];
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -110,6 +110,8 @@ void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
hw->rtc.commandActive = 0; hw->rtc.commandActive = 0;
hw->rtc.command = 0; hw->rtc.command = 0;
hw->rtc.control = 0x40; hw->rtc.control = 0x40;
hw->rtc.freeReg = 0;
hw->rtc.status2 = 0;
memset(hw->rtc.time, 0, sizeof(hw->rtc.time)); memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
} }
@ -216,15 +218,11 @@ void GBARTCProcessByte(struct GBARTC* rtc, struct mRTCSource* source) {
rtc->bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)]; rtc->bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
rtc->commandActive = rtc->bytesRemaining > 0; rtc->commandActive = rtc->bytesRemaining > 0;
switch (RTCCommandDataGetCommand(command)) { switch (RTCCommandDataGetCommand(command)) {
case RTC_RESET:
rtc->control = 0;
break;
case RTC_DATETIME: case RTC_DATETIME:
case RTC_TIME: case RTC_TIME:
_rtcUpdateClock(rtc, source); _rtcUpdateClock(rtc, source);
break; break;
case RTC_FORCE_IRQ: case RTC_FORCE_IRQ:
case RTC_CONTROL:
break; break;
} }
} else { } else {
@ -232,13 +230,18 @@ void GBARTCProcessByte(struct GBARTC* rtc, struct mRTCSource* source) {
} }
} else { } else {
switch (RTCCommandDataGetCommand(rtc->command)) { switch (RTCCommandDataGetCommand(rtc->command)) {
case RTC_CONTROL: case RTC_STATUS1:
rtc->control = rtc->bits; rtc->control = rtc->bits & 0xFE;
break; break;
case RTC_FORCE_IRQ: case RTC_FORCE_IRQ:
mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(rtc->command)); mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(rtc->command));
break; break;
case RTC_RESET: case RTC_STATUS2:
rtc->status2 = rtc->bits;
break;
case RTC_FREE_REG:
rtc->freeReg = rtc->bits;
break;
case RTC_DATETIME: case RTC_DATETIME:
case RTC_TIME: case RTC_TIME:
break; break;
@ -256,15 +259,19 @@ void GBARTCProcessByte(struct GBARTC* rtc, struct mRTCSource* source) {
unsigned GBARTCOutput(struct GBARTC* rtc) { unsigned GBARTCOutput(struct GBARTC* rtc) {
uint8_t outputByte = 0; uint8_t outputByte = 0;
switch (RTCCommandDataGetCommand(rtc->command)) { switch (RTCCommandDataGetCommand(rtc->command)) {
case RTC_CONTROL: case RTC_STATUS1:
outputByte = rtc->control; outputByte = rtc->control;
break; break;
case RTC_STATUS2:
outputByte = rtc->status2;
break;
case RTC_DATETIME: case RTC_DATETIME:
case RTC_TIME: case RTC_TIME:
outputByte = rtc->time[7 - rtc->bytesRemaining]; outputByte = rtc->time[7 - rtc->bytesRemaining];
break; break;
case RTC_FREE_REG:
outputByte = rtc->freeReg;
case RTC_FORCE_IRQ: case RTC_FORCE_IRQ:
case RTC_RESET:
break; break;
} }
unsigned output = (outputByte >> rtc->bitsRead) & 1; unsigned output = (outputByte >> rtc->bitsRead) & 1;
@ -291,6 +298,7 @@ void _rtcUpdateClock(struct GBARTC* rtc, struct mRTCSource* source) {
rtc->time[4] = _rtcBCD(date.tm_hour); rtc->time[4] = _rtcBCD(date.tm_hour);
} else { } else {
rtc->time[4] = _rtcBCD(date.tm_hour % 12); rtc->time[4] = _rtcBCD(date.tm_hour % 12);
rtc->time[4] |= (date.tm_hour >= 12) ? 0xC0 : 0;
} }
rtc->time[5] = _rtcBCD(date.tm_min); rtc->time[5] = _rtcBCD(date.tm_min);
rtc->time[6] = _rtcBCD(date.tm_sec); rtc->time[6] = _rtcBCD(date.tm_sec);
@ -574,8 +582,8 @@ void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASeria
STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead); STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits); STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive); STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
STORE_32(hw->rtc.command, 0, &state->hw.rtc.command); state->hw.rtc.command = hw->rtc.command;
STORE_32(hw->rtc.control, 0, &state->hw.rtc.control); state->hw.rtc.control = hw->rtc.control;
memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time)); memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
STORE_16(hw->gyroSample, 0, &state->hw.gyroSample); STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
@ -606,8 +614,8 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead); LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits); LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive); LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command); hw->rtc.command = state->hw.rtc.command;
LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control); hw->rtc.control = state->hw.rtc.control;
memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time)); memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample); LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);