From 0e66d077f8cf321c3f11978f531502ec592c0cdb Mon Sep 17 00:00:00 2001 From: Prakxo <87568477+Prakxo@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:02:29 +0200 Subject: lbrtc OK (#196) * lbrtc OK * format * names * format 2 * review + docs * format --- src/code/lb_rtc.c | 17 +++--- src/code/lbrtc/7220C0.c | 72 +++++++++++++++++++++++++ src/code/lbrtc/722570.c | 78 +++++++++++++++++++++++++++ src/code/lbrtc/722880.c | 26 +++++++++ src/code/lbrtc/722AB0.c | 120 +++++++++++++++++++++++++++++++++++++++++ src/code/lbrtc/lbrtc_getTime.c | 31 +++++++++++ src/code/lbrtc/lbrtc_init.c | 33 ++++++++++++ src/code/lbrtc/lbrtc_setTime.c | 41 ++++++++++++++ 8 files changed, 407 insertions(+), 11 deletions(-) create mode 100644 src/code/lbrtc/7220C0.c create mode 100644 src/code/lbrtc/722570.c create mode 100644 src/code/lbrtc/722880.c create mode 100644 src/code/lbrtc/722AB0.c create mode 100644 src/code/lbrtc/lbrtc_getTime.c create mode 100644 src/code/lbrtc/lbrtc_init.c create mode 100644 src/code/lbrtc/lbrtc_setTime.c (limited to 'src/code') diff --git a/src/code/lb_rtc.c b/src/code/lb_rtc.c index d9e6453..885fb90 100644 --- a/src/code/lb_rtc.c +++ b/src/code/lb_rtc.c @@ -1,12 +1,7 @@ #include "lb_rtc.h" +#include "lbrtc.h" #include "m_common_data.h" #include "padmgr.h" -#include "722970.h" -#include "721EC0.h" -#include "7220C0.h" -#include "722310.h" -#include "722AB0.h" -#include "722880.h" #include "macros.h" #include "attributes.h" @@ -22,7 +17,7 @@ s32 lbRTC_Initial() { if (l_lbRTC_isInitial == 1) { mq = padmgr_LockSerialMesgQ(); l_lbRTC_isInitial = 0; - B_80145620_jp = func_800FECD0_jp(mq); + B_80145620_jp = lbrtc_init(mq); padmgr_UnlockSerialMesgQ(mq); } return B_80145620_jp; @@ -36,7 +31,7 @@ s32 lbRTC_IsOki(lbRTC_time_c* ptr) { if (isInitial == 0) { mq = padmgr_LockSerialMesgQ(); - isInitial = func_800FE220_jp(mq, ptr); + isInitial = lbrtc_getTime(mq, ptr); padmgr_UnlockSerialMesgQ(mq); if (isInitial == 0) { return isInitial; @@ -97,7 +92,7 @@ void lbRTC_SetTime(lbRTC_time_c* time) { if (common_data.time.rtcEnabled == 1 && !common_data.time.rtcCrashed) { time->weekday = lbRTC_Week(time->year, time->month, time->day); mq = padmgr_LockSerialMesgQ(); - func_800FE670_jp(mq, time); + lbrtc_setTime(mq, time); padmgr_UnlockSerialMesgQ(mq); } else { lbRTC_TimeCopy(&common_data.time.rtcTime, time); @@ -109,7 +104,7 @@ void lbRTC_GetTime(lbRTC_time_c* time) { if (common_data.time.rtcEnabled == 1 && !common_data.time.rtcCrashed) { mq = padmgr_LockSerialMesgQ(); - func_800FE220_jp(mq, time); + lbrtc_getTime(mq, time); padmgr_UnlockSerialMesgQ(mq); } else { lbRTC_TimeCopy(time, &common_data.time.rtcTime); @@ -291,7 +286,7 @@ s32 lbRTC_IntervalTime(lbRTC_time_c* t0, lbRTC_time_c* t1) { t2 = *t0; t3 = *t1; - func_800FF060_jp(&t3, &t2); + lbrtc_GetIntervalMinutes(&t3, &t2); } const int total_days[2][lbRTC_MONTHS_MAX + 1] = { diff --git a/src/code/lbrtc/7220C0.c b/src/code/lbrtc/7220C0.c new file mode 100644 index 0000000..efbf300 --- /dev/null +++ b/src/code/lbrtc/7220C0.c @@ -0,0 +1,72 @@ +#include "lbrtc.h" +#include "lib/ultralib/src/io/siint.h" +#include "lib/ultralib/src/io/controller.h" + +s32 func_800FE420_jp(OSMesgQueue* mq, OSRTCTime* time) { + u8 status; + s32 ret; + + ret = func_800FE480_jp(mq, &status); + + if (ret == 0) { + ret = func_800FEE10_jp(mq, RTC_SRAM_BLOCK_TYPE, (u8*)time); + } + + return ret; +} + +s32 func_800FE480_jp(OSMesgQueue* mq, u8* status) { + s32 ret = 0; + s32 i; + u8* ptr; + __OSContRTCInfoFormat format; + + __osSiGetAccess(); + + __osEepPifRam.pifstatus = CONT_CMD_EXE; + + ptr = (u8*)&__osEepPifRam.ramarray; + + for (i = 0; i < 4; i++) { + *ptr++ = 0; + } + + format.txsize = CONT_CMD_RTC_INFO_TX; + format.rxsize = CONT_CMD_RTC_INFO_RX; + format.cmd = CONT_CMD_RTC_INFO; + + *(__OSContRTCInfoFormat*)ptr = format; + + ptr += sizeof(__OSContRTCInfoFormat); + + *ptr = CONT_CMD_END; + + ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osContLastCmd = CONT_CMD_RTC_INFO; + + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ptr = (u8*)&__osEepPifRam.ramarray[1]; + + format = *(__OSContRTCInfoFormat*)ptr; + + ret = (format.rxsize & CHNL_ERR_MASK) & 0xFF; + + if (ret == 0) { + if (!(((format.unk4 << 8) | format.unk3) & 0xFFFF & 0x1000)) { + ret = 0xB; + } else { + *status = format.status; + } + } else if (ret & CHNL_ERR_NORESP) { + ret = 1; + } else { + ret = 4; + } + + __osSiRelAccess(); + return ret; +} diff --git a/src/code/lbrtc/722570.c b/src/code/lbrtc/722570.c new file mode 100644 index 0000000..010815d --- /dev/null +++ b/src/code/lbrtc/722570.c @@ -0,0 +1,78 @@ +#include "lbrtc.h" +#include "lib/ultralib/src/io/siint.h" +#include "lib/ultralib/src/io/controller.h" + +OSTimer __contRTCTimer; +OSMesgQueue __contRTCMesgQ; +OSMesg __contRTCMesg; + +s32 func_800FE8D0_jp(OSMesgQueue* mq, u8 blockType, u8* data) { + s32 ret; + u8* ptr; + __OSContRTCRWFormat format; + + __osSiGetAccess(); + func_800FEABC_jp(blockType, data); + ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam); + __osContLastCmd = CONT_CMD_WRITE_RTC; + + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); + ptr = (u8*)(&__osEepPifRam.ramarray[1]); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + format = *((__OSContRTCRWFormat*)ptr); + ret = CHNL_ERR(format); + + __osSiRelAccess(); + + osSetTimer(&__contRTCTimer, OS_USEC_TO_CYCLES(300), 0, &__contRTCMesgQ, &__contRTCMesg); + osRecvMesg(&__contRTCMesgQ, NULL, OS_MESG_BLOCK); + if (ret == 0) { + bcopy(&format.data, data, sizeof(__OSContRTCData)); + if (format.status & RTC_STATUS_BATTERY_FAILURE) { + ret = RTC_ERR_BATTERY; + //! @bug should have checked for RTC_STATUS_CRYSTAL_FAILURE + } else if (format.status & RTC_STATUS_BATTERY_FAILURE) { + ret = RTC_ERR_CRYSTAL; + } else if (format.status & RTC_STATUS_STOPPED) { + ret = RTC_STOPPED; + } + } else if (ret & CHNL_ERR_NORESP) { + ret = 1; + } else { + ret = 4; + } + __osSiRelAccess(); + + return ret; +} + +s32 func_800FEABC_jp(u8 blockType, u8* data) { + s32 i; + u8* ptr = (u8*)&__osEepPifRam; + __OSContRTCRWFormat format; + + for (i = 0; i < ARRLEN(__osEepPifRam.ramarray); i++) { + __osEepPifRam.ramarray[i] = 0xFF; + } + + __osEepPifRam.pifstatus = CONT_CMD_EXE; + + format.txsize = CONT_CMD_WRITE_RTC_TX; + format.rxsize = CONT_CMD_WRITE_RTC_RX; + format.cmd = CONT_CMD_WRITE_RTC; + format.blockType = blockType; + + for (i = 0; i < (s32)sizeof(__OSContRTCData); i++) { + (&format.txsize)[i + 4] = *data++; + } + + for (i = 0; i < 4; i++) { + *ptr++ = 0; + } + *(__OSContRTCRWFormat*)ptr = format; + + ptr += sizeof(__OSContRTCRWFormat); + *ptr = CONT_CMD_END; +} diff --git a/src/code/lbrtc/722880.c b/src/code/lbrtc/722880.c new file mode 100644 index 0000000..6c57977 --- /dev/null +++ b/src/code/lbrtc/722880.c @@ -0,0 +1,26 @@ +#include "lbrtc.h" +#include "attributes.h" + +s32 func_800FEBE0_jp(OSMesgQueue* mq, OSRTCTime* time) { + u32 ret; + UNUSED s32 pad; + __OSContRTCControlRegs rtc[1]; + u8 status; + + ret = func_800FE480_jp(mq, &status); + if (ret == 0) { + ret = func_800FEE10_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&rtc); + if (ret == 0) { + rtc[0].writeProtectBitfield &= ~RTC_WRITE_PROTECT_NVRAM_BIT; + ret = func_800FE8D0_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&rtc); + if (ret == 0) { + ret = func_800FE8D0_jp(mq, RTC_SRAM_BLOCK_TYPE, (u8*)time); + if (ret == 0) { + rtc[0].writeProtectBitfield |= RTC_WRITE_PROTECT_NVRAM_BIT; + ret = func_800FE8D0_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&rtc); + } + } + } + } + return ret; +} diff --git a/src/code/lbrtc/722AB0.c b/src/code/lbrtc/722AB0.c new file mode 100644 index 0000000..0c1ed89 --- /dev/null +++ b/src/code/lbrtc/722AB0.c @@ -0,0 +1,120 @@ +#include "lbrtc.h" +#include "lb_rtc.h" +#include "lib/ultralib/src/io/siint.h" +#include "lib/ultralib/src/io/controller.h" + +u16 total_days_internal[2][lbRTC_MONTHS_MAX + 1] = { + // Standard year + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + // Leap year (flawed leap year calculation) + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + +s32 func_800FEE10_jp(OSMesgQueue* mq, u8 blockType, u8* buf) { + s32 ret; + __OSContRTCRWFormat* ptr; + __OSContRTCRWFormat format; + + __osSiGetAccess(); + func_800FEF9C_jp(blockType); + __osContLastCmd = CONT_CMD_READ_RTC; + + ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ptr = (__OSContRTCRWFormat*)&__osEepPifRam.ramarray[1]; + + format = *ptr; + ret = format.rxsize & CHNL_ERR_MASK; + + if (ret == 0) { + bcopy(&format.data, buf, 8); + if (format.status & RTC_STATUS_BATTERY_FAILURE) { + ret = RTC_ERR_BATTERY; + //! @bug should have checked for RTC_STATUS_CRYSTAL_FAILURE + } else if (format.status & RTC_STATUS_BATTERY_FAILURE) { + ret = RTC_ERR_CRYSTAL; + } else if (format.status & RTC_STATUS_STOPPED) { + ret = RTC_STOPPED; + } + } else if (ret & CHNL_ERR_NORESP) { + ret = 1; + } else { + ret = 4; + } + + __osSiRelAccess(); + return ret; +} + +void func_800FEF9C_jp(u8 blockType) { + u8* ptr = (u8*)&__osEepPifRam.ramarray; + s32 i; + __OSContRTCRWFormat format; + + __osEepPifRam.pifstatus = CONT_CMD_EXE; + + format.txsize = CONT_CMD_READ_RTC_TX; + format.rxsize = CONT_CMD_READ_RTC_RX; + format.cmd = CONT_CMD_READ_RTC; + format.blockType = blockType; + + for (i = 0; i < 4; i++) { + *ptr++ = 0; + } + + *(__OSContRTCRWFormat*)ptr = format; + + ptr += sizeof(__OSContRTCRWFormat); + *ptr = CONT_CMD_END; +} + +s32 lbrtc_GetIntervalMinutes(OSRTCTime* t0, OSRTCTime* t1) { + u8 yearLeapPeriod = (t1->year - t0->year) / 4; + /* Total 'leap years' (missing extra not divisible by 100, except when divisible by 400 rule) */ + + u8 extraYears = (t1->year - t0->year) % 4; /* Non-leap year remainder */ + u8 lessLeap = (t0->year % 4) == 0; /* Is the lesser year a leap year? */ + u8 overLeap = (t1->year % 4) == 0; /* Is the greater year a leap year? */ + u8 leapAdd = ((4 - (t0->year % 4)) % 4) < extraYears; /* Add leap day when leap day occurs during 'extra years' */ + + s32 days; + s32 hour; + s32 min; + if (t0->year > t1->year) { + return 0; + } else if (t0->year == t1->year) { + if (t0->month > t1->month) { + return 0; + } else if (t0->month == t1->month) { + if (t0->day > t1->day) { + return 0; + } else if (t0->day == t1->day) { + if (t0->hour > t1->hour) { + return 0; + } else if (t0->hour == t1->hour) { + if (t0->min > t1->min) { + return 0; + } + } + } + } + } + + days = yearLeapPeriod * 1461 + extraYears * 365 + leapAdd; + days += t1->day - 1; + days += total_days_internal[overLeap][t1->month - 1]; + days -= t0->day - 1; + days -= total_days_internal[lessLeap][t0->month - 1]; + + hour = days * 24; + hour = (t1->hour + hour) - t0->hour; + + min = hour * 60; + min = (t1->min + min) - t0->min; + + return min; +} diff --git a/src/code/lbrtc/lbrtc_getTime.c b/src/code/lbrtc/lbrtc_getTime.c new file mode 100644 index 0000000..4dd8669 --- /dev/null +++ b/src/code/lbrtc/lbrtc_getTime.c @@ -0,0 +1,31 @@ +#include "lbrtc.h" + +s32 lbrtc_getTime(OSMesgQueue* mq, OSRTCTime* time) { + __OSContRTCData rtc[1]; + __OSContRTCData data; + u8 status; + s32 ret; + + ret = func_800FE480_jp(mq, &status); + if (ret == 0) { + ret = func_800FEE10_jp(mq, RTC_TIME_BLOCK_TYPE, (u8*)&data); + if (ret == 0) { + ret = func_800FEE10_jp(mq, RTC_TIME_BLOCK_TYPE, (u8*)&rtc); + if (bcmp(&data, &rtc, sizeof(__OSContRTCData)) != 0) { + ret = func_800FEE10_jp(mq, RTC_TIME_BLOCK_TYPE, (u8*)&rtc); + } + time->sec = (rtc[0].sec & 0xF) + ((rtc[0].sec >> 4) * 10); + time->min = (rtc[0].min & 0xF) + ((rtc[0].min >> 4) * 10); + time->hour = (((rtc[ret * 0].hour - 0x80) >> 4) * 10) + (((rtc + 0)->hour - 0x80) & 0xF); + time->day = (rtc[0].day & 0xF) + ((rtc[0].day >> 4) * 10); + time->weekday = rtc[0].weekday; + time->month = (rtc[0].month & 0xF) + ((rtc[0].month >> 4) * 10); + if (rtc[0].centuriesSince1900 != 0) { + time->year = ((rtc[0].yearLo & 0xF) + ((rtc[0].yearLo >> 4) * 10)) + 2000; + } else { + time->year = ((rtc[0].yearLo & 0xF) + ((rtc[0].yearLo >> 4) * 10)) + 1900; + } + } + } + return ret; +} diff --git a/src/code/lbrtc/lbrtc_init.c b/src/code/lbrtc/lbrtc_init.c new file mode 100644 index 0000000..e298065 --- /dev/null +++ b/src/code/lbrtc/lbrtc_init.c @@ -0,0 +1,33 @@ +#include "lbrtc.h" +#include "attributes.h" + +s32 D_801160C0_jp = 0; + +s32 lbrtc_init(OSMesgQueue* mq) { + s32 ret; + u8 status; + UNUSED s32 pad; + __OSContRTCControlRegs rtc[1]; + + ret = func_800FE480_jp(mq, &status); + if (ret == 0) { + if (D_801160C0_jp == 0) { + osCreateMesgQueue(&__contRTCMesgQ, &__contRTCMesg, OS_MESG_BLOCK); + D_801160C0_jp = 1; + } + if (status & RTC_STATUS_STOPPED) { + ret = func_800FEE10_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&rtc); + if ((ret == 0) || (ret == RTC_STOPPED)) { + rtc[0].flagsBitfield &= ~RTC_WRITE_STOP_COUNT2_BIT; + ret = func_800FE8D0_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&rtc); + } + } + if (status & RTC_STATUS_BATTERY_FAILURE) { + ret = (status & RTC_STATUS_CRYSTAL_FAILURE) ? 0x13 : RTC_ERR_BATTERY; + + } else if (status & RTC_STATUS_CRYSTAL_FAILURE) { + ret = RTC_ERR_CRYSTAL; + } + } + return ret; +} diff --git a/src/code/lbrtc/lbrtc_setTime.c b/src/code/lbrtc/lbrtc_setTime.c new file mode 100644 index 0000000..900803d --- /dev/null +++ b/src/code/lbrtc/lbrtc_setTime.c @@ -0,0 +1,41 @@ +#include "lbrtc.h" +#include "attributes.h" + +s32 lbrtc_setTime(OSMesgQueue* mq, OSRTCTime* time) { + __OSContRTCData rtc[1]; + UNUSED s32 pad; + __OSContRTCControlRegs cr[1]; + u8 status; + s32 ret; + + ret = func_800FE480_jp(mq, &status); + if (ret == 0) { + ret = func_800FEE10_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&cr); + if (ret == 0) { + cr[0].writeProtectBitfield &= ~RTC_WRITE_PROTECT_RTC_BIT; + cr[0].flagsBitfield |= RTC_WRITE_STOP_COUNT_BIT; + ret = func_800FE8D0_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&cr); + if (ret == RTC_STOPPED) { + rtc[0].sec = (time->sec % 10) + ((time->sec / 10) * 0x10); + rtc[0].min = (time->min % 10) + ((time->min / 10) * 0x10); + rtc[0].hour = (time->hour % 10) + ((time->hour / 10) * 0x10); + rtc[0].day = (time->day % 10) + ((time->day / 10) * 0x10); + rtc[0].weekday = time->weekday; + rtc[0].month = (time->month % 10) + ((time->month / 10) * 0x10); + rtc[0].yearLo = (time->year % 10) + (((time->year % 100) / 10) * 0x10); + if (time->year >= 2000) { + rtc[0].centuriesSince1900 = 1; + } else { + rtc[0].centuriesSince1900 = 0; + } + ret = func_800FE8D0_jp(mq, RTC_TIME_BLOCK_TYPE, (u8*)&rtc); + if (ret == RTC_STOPPED) { + cr[0].writeProtectBitfield |= RTC_WRITE_PROTECT_RTC_BIT; + cr[0].flagsBitfield &= ~RTC_WRITE_STOP_COUNT_BIT; + ret = func_800FE8D0_jp(mq, RTC_CR_BLOCK_TYPE, (u8*)&cr); + } + } + } + } + return ret; +} -- cgit v1.2.3