summaryrefslogtreecommitdiff
path: root/arm9/src/gf_rtc.c
blob: 02fa735f3f8103a388e867e2a744614e33abff01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include "global.h"
#include "MI_memory.h"
#include "gf_rtc.h"
#include "RTC_convert.h"

typedef struct GF_RTC_Work
{
    BOOL getDateTimeSuccess;
    BOOL getDateTimeLock;
    s32 getDateTimeSleep;
    RTCResult getDateTimeErrorCode;
    RTCDate date; // 10
    RTCTime time; // 20
    RTCDate date_async; // 2C
    RTCTime time_async; // 3C
} GF_RTC_Work;

GF_RTC_Work sGFRTCWork;

#define MAX_SECONDS     (3155759999ll)

void GF_RTC_GetDateTime(GF_RTC_Work * work);

THUMB_FUNC void GF_InitRTCWork(void)
{
    RTC_Init();
    __builtin__clear(&sGFRTCWork, sizeof(sGFRTCWork));
    sGFRTCWork.getDateTimeSuccess = FALSE;
    sGFRTCWork.getDateTimeLock = FALSE;
    sGFRTCWork.getDateTimeSleep = 0;
    GF_RTC_GetDateTime(&sGFRTCWork);
}

THUMB_FUNC void GF_RTC_UpdateOnFrame(void)
{
    if (!sGFRTCWork.getDateTimeLock)
    {
        if (++sGFRTCWork.getDateTimeSleep > 10)
        {
            sGFRTCWork.getDateTimeSleep = 0;
            GF_RTC_GetDateTime(&sGFRTCWork);
        }
    }
}

THUMB_FUNC void GF_RTC_GetDateTime_Callback(RTCResult result, void * data)
{
    GF_RTC_Work * work = (GF_RTC_Work *)data;
    work->getDateTimeErrorCode = result;
    GF_ASSERT(result == RTC_RESULT_SUCCESS);
    work->getDateTimeSuccess = TRUE;
    work->date = work->date_async;
    work->time = work->time_async;
    work->getDateTimeLock = FALSE;
}

THUMB_FUNC void GF_RTC_GetDateTime(GF_RTC_Work * work)
{
    work->getDateTimeLock = TRUE;
    RTCResult result = RTC_GetDateTimeAsync(&work->date_async, &work->time_async, GF_RTC_GetDateTime_Callback, work);
    work->getDateTimeErrorCode = result;
    GF_ASSERT(result == RTC_RESULT_SUCCESS);
}

THUMB_FUNC void GF_RTC_CopyDateTime(RTCDate * date, RTCTime * time)
{
    GF_ASSERT(sGFRTCWork.getDateTimeSuccess == TRUE);
    *date = sGFRTCWork.date;
    *time = sGFRTCWork.time;
}

THUMB_FUNC void GF_RTC_CopyTime(RTCTime * time)
{
    GF_ASSERT(sGFRTCWork.getDateTimeSuccess == TRUE);
    *time = sGFRTCWork.time;
}

THUMB_FUNC void GF_RTC_CopyDate(RTCDate * date)
{
    GF_ASSERT(sGFRTCWork.getDateTimeSuccess == TRUE);
    *date = sGFRTCWork.date;
}

THUMB_FUNC s32 GF_RTC_TimeToSec(void)
{
    RTCTime* time = &sGFRTCWork.time;
    return 60 * time->minute + 3600 * time->hour + time->second;
}

THUMB_FUNC s64 GF_RTC_DateTimeToSec(void)
{
    return RTC_ConvertDateTimeToSecond(&sGFRTCWork.date, &sGFRTCWork.time);
}

static inline BOOL IsLeapYear(s32 year)
{
    return ((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0);
}

THUMB_FUNC s32 GF_RTC_GetDayOfYear(const RTCDate * date)
{
    RTCDate date_stack;
    s32 days;
    static const u16 sGF_DaysPerMonth[] = {
        0,   // Jan
        31,  // Feb
        59,  // Mar
        90,  // Apr
        120, // May
        151, // Jun
        181, // Jul
        212, // Aug
        243, // Sep
        273, // Oct
        304, // Nov
        334, // Dec
    };

    days = date->day;
    days += sGF_DaysPerMonth[date->month - 1];
    if (date->month >= RTC_MONTH_MARCH && IsLeapYear(date->year))
        days++;
    date_stack = *date;
    date_stack.month = RTC_MONTH_JANUARY;
    date_stack.day = 1;
    RTC_ConvertDateToDay(&date_stack);
    RTC_ConvertDateToDay(date);
    return days;
}

enum RTC_TimeOfDay GF_RTC_GetTimeOfDay(void);
enum RTC_TimeOfDay GF_RTC_GetTimeOfDayByHour(s32 hour);

THUMB_FUNC BOOL IsNighttime(void)
{
    switch (GF_RTC_GetTimeOfDay())
    {
        case RTC_TIMEOFDAY_NITE:
        case RTC_TIMEOFDAY_LATE:
            return TRUE;
        default:
            return FALSE;
    }
}

THUMB_FUNC enum RTC_TimeOfDay GF_RTC_GetTimeOfDay(void)
{
    RTCTime time;
    GF_RTC_CopyTime(&time);
    return GF_RTC_GetTimeOfDayByHour(time.hour);
}

THUMB_FUNC enum RTC_TimeOfDay GF_RTC_GetTimeOfDayByHour(s32 hour)
{
    static const u8 sTimeOfDayByHour[] = {
        // 00:00 - 03:59
        RTC_TIMEOFDAY_LATE, RTC_TIMEOFDAY_LATE, RTC_TIMEOFDAY_LATE, RTC_TIMEOFDAY_LATE,
        // 04:00 - 09:59
        RTC_TIMEOFDAY_MORN, RTC_TIMEOFDAY_MORN, RTC_TIMEOFDAY_MORN, RTC_TIMEOFDAY_MORN, RTC_TIMEOFDAY_MORN, RTC_TIMEOFDAY_MORN,
        // 10:00 - 16:59
        RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY, RTC_TIMEOFDAY_DAY,
        // 17:00 - 19:59
        RTC_TIMEOFDAY_EVE, RTC_TIMEOFDAY_EVE, RTC_TIMEOFDAY_EVE,
        // 20:00 - 23:59
        RTC_TIMEOFDAY_NITE, RTC_TIMEOFDAY_NITE, RTC_TIMEOFDAY_NITE, RTC_TIMEOFDAY_NITE,
    };

    GF_ASSERT(hour >= 0 && hour < 24);
    return sTimeOfDayByHour[hour];
}

THUMB_FUNC s64 GF_RTC_TimeDelta(s64 first, s64 last)
{
    RTCDate maxDate = { 99, 12, 31, 0 };
    RTCTime maxTime = { 23, 59, 59 };

    s64 check = RTC_ConvertDateTimeToSecond(&maxDate, &maxTime);
    GF_ASSERT(check == MAX_SECONDS);
    if (first < last)
        return last - first;
    else
        return last + (MAX_SECONDS - first);
}