Files
af/src/code/lb_rtc.c
T
Prakxo e1fcb33cef The NPC PR 3/3 OK (#119)
* npc werk

* atleast it builds

* m_npc OK

* forgor format

* review

* format

* fix warns?
2023-11-23 10:03:30 -07:00

594 lines
14 KiB
C

#include "lb_rtc.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"
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 = func_800FECD0_jp(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 = func_800FE220_jp(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();
func_800FE670_jp(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();
func_800FE220_jp(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;
func_800FF060_jp(&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;
}