mirror of https://github.com/mgba-emu/mgba.git
GBA Hardware: Begin fixing RTC implementation
This commit is contained in:
parent
53778e8d92
commit
a278899314
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue