#include "lb_rtc.h" #include "lbrtc.h" #include "m_common_data.h" #include "padmgr.h" #include "macros.h" #include "attributes.h" s32 l_lbRTC_isInitial = 1; s32 l_lbRTC_IsSampled = 0; s32 B_80145620_jp; lbRTC_time_c l_lbRTC_Time; s32 lbRTC_Initial() { OSMesgQueue* mq; if (l_lbRTC_isInitial == 1) { mq = padmgr_LockSerialMesgQ(); l_lbRTC_isInitial = 0; B_80145620_jp = lbrtc_init(mq); padmgr_UnlockSerialMesgQ(mq); } return B_80145620_jp; } s32 lbRTC_IsOki(lbRTC_time_c* ptr) { s32 isInitial; OSMesgQueue* mq; isInitial = lbRTC_Initial(); if (isInitial == 0) { mq = padmgr_LockSerialMesgQ(); isInitial = lbrtc_getTime(mq, ptr); padmgr_UnlockSerialMesgQ(mq); if (isInitial == 0) { return isInitial; } } l_lbRTC_isInitial = 1; return isInitial; } s32 lbRTC_IsAbnormal() { lbRTC_time_c time; s32 temp UNUSED; s32 res = lbRTC_IsOki(&time); if ((res == 0) && (l_lbRTC_IsSampled == 1)) { s32 baseTimer = (l_lbRTC_Time.sec + (l_lbRTC_Time.min * 60)); if ((time.sec + (time.min * 60)) != baseTimer) { return res; } } return res; } void lbRTC_Sampling() { lbRTC_time_c time; if ((lbRTC_IsOki(&time) == 0) && (!l_lbRTC_IsSampled)) { l_lbRTC_Time.sec = time.sec; l_lbRTC_Time.min = time.min; l_lbRTC_IsSampled = 1; } } void func_800D4F6C_jp(lbRTC_time_c* time) { OSMesgQueue* mq; if (lbRTC_Initial() == 0) { mq = padmgr_LockSerialMesgQ(); func_800FEBE0_jp(mq, time); padmgr_UnlockSerialMesgQ(mq); } } void func_800D4FB8_jp(lbRTC_time_c* time) { OSMesgQueue* mq; if (lbRTC_Initial() == 0) { mq = padmgr_LockSerialMesgQ(); func_800FE420_jp(mq, time); padmgr_UnlockSerialMesgQ(mq); } } void lbRTC_SetTime(lbRTC_time_c* time) { OSMesgQueue* mq; if (common_data.time.rtcEnabled == 1 && !common_data.time.rtcCrashed) { time->weekday = lbRTC_Week(time->year, time->month, time->day); mq = padmgr_LockSerialMesgQ(); lbrtc_setTime(mq, time); padmgr_UnlockSerialMesgQ(mq); } else { lbRTC_TimeCopy(&common_data.time.rtcTime, time); } } void lbRTC_GetTime(lbRTC_time_c* time) { OSMesgQueue* mq; if (common_data.time.rtcEnabled == 1 && !common_data.time.rtcCrashed) { mq = padmgr_LockSerialMesgQ(); lbrtc_getTime(mq, time); padmgr_UnlockSerialMesgQ(mq); } else { lbRTC_TimeCopy(time, &common_data.time.rtcTime); } } const lbRTC_day_t days_month[2][lbRTC_MONTHS_MAX + 1] = { // Regular year { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, // Leap year { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; lbRTC_day_t lbRTC_GetDaysByMonth(lbRTC_year_t year, lbRTC_month_t month) { s32 leap = !(year & 3) ? 1 : 0; s32 idx = leap == 1 ? 1 : 0; return days_month[idx][month]; } typedef union lbRTCYMD { s32 raw; lbRTC_ymd_t ymd; } lbRTCYMD; s32 lbRTC_IsEqualDate(lbRTC_year_t y0, lbRTC_month_t m0, lbRTC_day_t d0, lbRTC_year_t y1, lbRTC_month_t m1, lbRTC_day_t d1) { lbRTCYMD ymd0; lbRTCYMD ymd1; s32 res; ymd0.ymd.year = y0; ymd0.ymd.month = m0; ymd0.ymd.day = d0; ymd1.ymd.year = y1; ymd1.ymd.month = m1; ymd1.ymd.day = d1; res = ymd0.raw - ymd1.raw; if (res == 0) { return lbRTC_EQUAL; } if (res < 0) { return lbRTC_LESS; } return lbRTC_OVER; } s32 lbRTC_IsEqualTime(const lbRTC_time_c* t0, const lbRTC_time_c* t1, s32 flags) { s32 equal = 0; if (flags & lbRTC_CHECK_SECONDS) { if (t0->sec == t1->sec) { equal |= lbRTC_CHECK_SECONDS; } } if (flags & lbRTC_CHECK_MINUTES) { if (t0->min == t1->min) { equal |= lbRTC_CHECK_MINUTES; } } if (flags & lbRTC_CHECK_HOURS) { if (t0->hour == t1->hour) { equal |= lbRTC_CHECK_HOURS; } } if (flags & lbRTC_CHECK_WEEKDAYS) { if (t0->weekday == t1->weekday) { equal |= lbRTC_CHECK_WEEKDAYS; } } if (flags & lbRTC_CHECK_DAYS) { if (t0->day == t1->day) { equal |= lbRTC_CHECK_DAYS; } } if (flags & lbRTC_CHECK_MONTHS) { if (t0->month == t1->month) { equal |= lbRTC_CHECK_MONTHS; } } if (flags & lbRTC_CHECK_YEARS) { if (t0->year == t1->year) { equal |= lbRTC_CHECK_YEARS; } } return flags == (equal & flags); } s32 lbRTC_IsOverTime(const lbRTC_time_c* t0, const lbRTC_time_c* t1) { if (t1->year < t0->year) { return lbRTC_LESS; } if (t1->year == t0->year) { if (t1->month >= t0->month) { if (t1->month == t0->month) { if (t1->day >= t0->day) { if (t1->day == t0->day) { if (t1->hour >= t0->hour) { if (t1->hour == t0->hour) { if (t1->min >= t0->min) { if (t1->min == t0->min) { if (t1->sec < t0->sec) { return lbRTC_LESS; } } } else { return lbRTC_LESS; } } } else { return lbRTC_LESS; } } } else { return lbRTC_LESS; } } } else { return lbRTC_LESS; } } return lbRTC_OVER; } s32 lbRTC_IsJustAtRTC(const lbRTC_time_c* time, s32 flags) { lbRTC_time_c rtcTime; lbRTC_GetTime(&rtcTime); return lbRTC_IsEqualTime(&rtcTime, time, flags); } s32 lbRTC_IsOverRTC(const lbRTC_time_c* time) { lbRTC_time_c rtcTime; lbRTC_GetTime(&rtcTime); return lbRTC_IsOverTime(time, &rtcTime) == lbRTC_OVER; } s32 lbRTC_IsOverWeekRTC(const lbRTC_time_c* t0, lbRTC_weekday_t week) { s32 curWeek; lbRTC_time_c t1; curWeek = week - t0->weekday; t1 = *t0; if (curWeek <= 0) { curWeek += 7; } t1.hour = 0; t1.min = 0; t1.sec = 0; lbRTC_Add_DD(&t1, curWeek); lbRTC_IsOverRTC(&t1); } s32 lbRTC_IntervalTime(lbRTC_time_c* t0, lbRTC_time_c* t1) { lbRTC_time_c t2; lbRTC_time_c t3; t2 = *t0; t3 = *t1; lbrtc_GetIntervalMinutes(&t3, &t2); } const int total_days[2][lbRTC_MONTHS_MAX + 1] = { // Standard year { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, // Leap year { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; s32 lbRTC_GetIntervalDays(const lbRTC_time_c* t0, const lbRTC_time_c* t1) { s32 leapPeriod = (t1->year - t0->year) / 4; s32 years = (t1->year - t0->year) % 4; s32 lessLeap = (t0->year % 4) == 0; s32 overLeap = (t1->year % 4) == 0; s32 leapAdd = ((4 - (t0->year % 4)) % 4) < years; s32 days; 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 = leapPeriod * 1461 + years * 365 + leapAdd; days += t1->day - 1; days += total_days[overLeap][t1->month - 1]; days -= t0->day - 1; days -= total_days[lessLeap][t0->month - 1]; return days; } void lbRTC_Add_YY(lbRTC_time_c* time, s32 years) { time->year += (u16)years; } void lbRTC_Add_MM(lbRTC_time_c* time, s32 month) { s32 timeMonth = time->month; timeMonth += month; if (timeMonth > lbRTC_MONTHS_MAX) { lbRTC_Add_YY(time, timeMonth / lbRTC_MONTHS_MAX); timeMonth %= lbRTC_MONTHS_MAX; } time->month = (lbRTC_month_t)timeMonth; } void lbRTC_Add_DD(lbRTC_time_c* time, s32 day) { s32 days = lbRTC_GetDaysByMonth(time->year, (lbRTC_month_t)time->month); s32 timeDay = time->day; timeDay += day; if (timeDay > days) { timeDay -= days; lbRTC_Add_MM(time, 1); } time->day = (lbRTC_day_t)timeDay; } void lbRTC_Add_hh(lbRTC_time_c* time, s32 hour) { s32 timeHour = time->hour; timeHour += hour; if (timeHour >= lbRTC_HOURS_PER_DAY) { lbRTC_Add_DD(time, timeHour / lbRTC_HOURS_PER_DAY); timeHour %= lbRTC_HOURS_PER_DAY; } time->hour = (lbRTC_hour_t)timeHour; } void lbRTC_Add_mm(lbRTC_time_c* time, s32 min) { s32 timeSec = time->min; timeSec += min; if (timeSec >= lbRTC_MINUTES_PER_HOUR) { lbRTC_Add_hh(time, timeSec / lbRTC_MINUTES_PER_HOUR); timeSec %= lbRTC_MINUTES_PER_HOUR; } time->min = (lbRTC_min_t)timeSec; } void lbRTC_Add_ss(lbRTC_time_c* time, s32 sec) { int timeSec = time->sec; timeSec += sec; if (timeSec >= lbRTC_SECONDS_PER_MINUTE) { lbRTC_Add_mm(time, timeSec / lbRTC_SECONDS_PER_MINUTE); timeSec %= lbRTC_SECONDS_PER_MINUTE; } time->sec = (lbRTC_sec_t)timeSec; } void lbRTC_Add_Date(lbRTC_time_c* time, const lbRTC_time_c* add_time) { lbRTC_Add_ss(time, add_time->sec); lbRTC_Add_mm(time, add_time->min); lbRTC_Add_hh(time, add_time->hour); lbRTC_Add_DD(time, add_time->day); lbRTC_Add_MM(time, add_time->month); lbRTC_Add_YY(time, add_time->year); } void lbRTC_Sub_YY(lbRTC_time_c* time, s32 year) { time->year -= (lbRTC_year_t)year; } void lbRTC_Sub_MM(lbRTC_time_c* time, s32 month) { s32 calcMonth = time->month - month; if (calcMonth < 1) { s32 temp = calcMonth; s32 year; if (calcMonth == 0) { calcMonth = lbRTC_MONTHS_MAX; year = 1; } else { temp = ABS(calcMonth); year = temp / lbRTC_MONTHS_MAX + 1; calcMonth = lbRTC_MONTHS_MAX - (temp % lbRTC_MONTHS_MAX); } lbRTC_Sub_YY(time, year); } time->month = (lbRTC_month_t)calcMonth; } void lbRTC_Sub_DD(lbRTC_time_c* time, s32 days) { s32 currentDay = time->day; s32 day; if (time->month == lbRTC_JANUARY) { day = lbRTC_GetDaysByMonth(time->year, lbRTC_MONTHS_MAX); } else { day = lbRTC_GetDaysByMonth(time->year, (time->month - 1)); } currentDay -= days; if (currentDay <= 0) { if (currentDay == 0) { currentDay = day; } else { currentDay += day; } lbRTC_Sub_MM(time, 1); } time->day = (lbRTC_day_t)currentDay; } void lbRTC_Sub_hh(lbRTC_time_c* time, s32 hour) { s32 timeHour = time->hour; timeHour -= hour; if (timeHour < 0) { s32 temp = timeHour; s32 days; temp = ABS(timeHour); days = temp / lbRTC_HOURS_PER_DAY + 1; timeHour = lbRTC_HOURS_PER_DAY - (temp % lbRTC_HOURS_PER_DAY); if (timeHour == lbRTC_HOURS_PER_DAY) { timeHour = 0; days--; } lbRTC_Sub_DD(time, days); } time->hour = (lbRTC_hour_t)timeHour; } void lbRTC_Sub_mm(lbRTC_time_c* time, s32 min) { s32 timeMin = time->min; timeMin -= min; if (timeMin < 0) { s32 temp = timeMin; s32 hours; temp = ABS(timeMin); hours = temp / lbRTC_MINUTES_PER_HOUR + 1; timeMin = lbRTC_MINUTES_PER_HOUR - (temp % lbRTC_MINUTES_PER_HOUR); if (timeMin == lbRTC_MINUTES_PER_HOUR) { timeMin = 0; hours--; } lbRTC_Sub_hh(time, hours); } time->min = (lbRTC_min_t)timeMin; } void lbRTC_Sub_ss(lbRTC_time_c* time, s32 sec) { s32 timeSec = time->sec; timeSec -= sec; if (timeSec < 0) { s32 temp = timeSec; s32 mins; temp = ABS(timeSec); mins = temp / lbRTC_SECONDS_PER_MINUTE + 1; timeSec = lbRTC_SECONDS_PER_MINUTE - (temp % lbRTC_SECONDS_PER_MINUTE); if (timeSec == lbRTC_SECONDS_PER_MINUTE) { timeSec = 0; mins--; } lbRTC_Sub_mm(time, mins); } time->sec = (lbRTC_sec_t)timeSec; } void lbRTC_Sub_Date(lbRTC_time_c* time, const lbRTC_time_c* sub_time) { lbRTC_Sub_ss(time, sub_time->sec); lbRTC_Sub_mm(time, sub_time->min); lbRTC_Sub_hh(time, sub_time->hour); lbRTC_Sub_DD(time, sub_time->day); lbRTC_Sub_MM(time, sub_time->month); lbRTC_Sub_YY(time, sub_time->year); } const lbRTC_time_c a_time = { 0, 0, 0, 1, 0, 1, 1901 }; lbRTC_weekday_t lbRTC_Week(lbRTC_year_t year, lbRTC_month_t month, lbRTC_day_t day) { lbRTC_time_c b_time = { 0, 0, 0, 0, 0, 0, 0000 }; b_time.year = year; b_time.month = month; b_time.day = day; return (lbRTC_weekday_t)((lbRTC_GetIntervalDays(&a_time, &b_time) + 2) % lbRTC_WEEKDAYS_MAX); } void lbRTC_TimeCopy(lbRTC_time_c* dst, const lbRTC_time_c* src) { *dst = *src; } const lbRTC_day_t day_tbl[] = { 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; s32 lbRTC_IsValidTime(const lbRTC_time_c* time) { s32 res; if ((time->year < lbRTC_YEAR_MIN || time->year > lbRTC_YEAR_MAX) || (time->month == lbRTC_MONTHS_BEGIN) || (time->month > lbRTC_MONTHS_MAX) || (time->day == 0) || (time->hour > lbRTC_HOURS_PER_DAY - 1) || (time->min > lbRTC_MINUTES_PER_HOUR - 1) || (time->sec > lbRTC_SECONDS_PER_MINUTE - 1)) { res = 0; } else { if (time->day == 29 && time->month == lbRTC_FEBRUARY) { res = !(time->year & 3) ? 1 : 0; } else if (time->day > day_tbl[time->month]) { res = 0; } else { res = 1; } } return res; }