refactor: more compact log message
[lunaix-os.git] / lunaix-os / kernel / time / clock.c
1 #include <hal/rtc.h>
2 #include <lunaix/clock.h>
3 #include <lunaix/fs/twifs.h>
4 #include <lunaix/spike.h>
5 #include <lunaix/timer.h>
6
7 static volatile time_t sys_time;
8
9 void
10 clock_systime_counter(void* arg);
11
12 void
13 __clock_read_systime(struct twimap* map)
14 {
15     time_t save = sys_time;
16     twimap_printf(map, "%u", save);
17 }
18
19 void
20 __clock_read_datetime(struct twimap* map)
21 {
22     datetime_t dt;
23     clock_walltime(&dt);
24     twimap_printf(map,
25                   "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
26                   dt.year,
27                   dt.month,
28                   dt.day,
29                   dt.hour,
30                   dt.minute,
31                   dt.second);
32 }
33
34 void
35 __clock_read_unix(struct twimap* map)
36 {
37     datetime_t dt;
38     clock_walltime(&dt);
39     twimap_printf(map, "%u", clock_tounixtime(&dt));
40 }
41
42 void
43 clock_build_mapping()
44 {
45     struct twifs_node* root = twifs_dir_node(NULL, "clock");
46     struct twimap* map;
47
48     map = twifs_mapping(root, NULL, "systime");
49     map->read = __clock_read_systime;
50
51     map = twifs_mapping(root, NULL, "unix");
52     map->read = __clock_read_unix;
53
54     map = twifs_mapping(root, NULL, "datetime");
55     map->read = __clock_read_datetime;
56 }
57
58 void
59 clock_init()
60 {
61     if (!timer_context()) {
62         panick("Systimer not initialized");
63     }
64
65     // 系统计时器每毫秒累加。
66     timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC);
67
68     clock_build_mapping();
69 }
70
71 void
72 clock_systime_counter(void* arg)
73 {
74     sys_time++;
75 }
76
77 int
78 clock_datatime_eq(datetime_t* a, datetime_t* b)
79 {
80     return a->year == b->year && a->month == b->month && a->day == b->day &&
81            a->weekday == b->weekday && a->minute == b->minute &&
82            a->second == b->second;
83 }
84
85 void
86 clock_walltime(datetime_t* datetime)
87 {
88     datetime_t current;
89
90     do {
91         while (rtc_read_reg(RTC_REG_A) & 0x80)
92             ;
93         memcpy(&current, datetime, sizeof(datetime_t));
94
95         datetime->year = rtc_read_reg(RTC_REG_YRS);
96         datetime->month = rtc_read_reg(RTC_REG_MTH);
97         datetime->day = rtc_read_reg(RTC_REG_DAY);
98         datetime->weekday = rtc_read_reg(RTC_REG_WDY);
99         datetime->hour = rtc_read_reg(RTC_REG_HRS);
100         datetime->minute = rtc_read_reg(RTC_REG_MIN);
101         datetime->second = rtc_read_reg(RTC_REG_SEC);
102     } while (!clock_datatime_eq(datetime, &current));
103
104     uint8_t regbv = rtc_read_reg(RTC_REG_B);
105
106     // Convert from bcd to binary when needed
107     if (!RTC_BIN_ENCODED(regbv)) {
108         datetime->year = bcd2dec(datetime->year);
109         datetime->month = bcd2dec(datetime->month);
110         datetime->day = bcd2dec(datetime->day);
111         datetime->hour = bcd2dec(datetime->hour);
112         datetime->minute = bcd2dec(datetime->minute);
113         datetime->second = bcd2dec(datetime->second);
114     }
115
116     // To 24 hour format
117     if (!RTC_24HRS_ENCODED(regbv) && (datetime->hour >> 7)) {
118         datetime->hour = (12 + datetime->hour & 0x80);
119     }
120
121     datetime->year += RTC_CURRENT_CENTRY * 100;
122 }
123
124 time_t
125 clock_unixtime()
126 {
127     datetime_t dt;
128     clock_walltime(&dt);
129     return clock_tounixtime(&dt);
130 }
131
132 time_t
133 clock_systime()
134 {
135     return sys_time;
136 }