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