|
|
1.1 root 1: //
2: // nono
1.1.1.3 ! root 3: // Copyright (C) 2020 nono project
! 4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "rtc.h"
8: #include <sys/time.h>
9:
10: // XXX rtc の読み書きはロックしたほうがいいような気がする
11:
1.1.1.2 root 12: std::unique_ptr<RTCDevice> gRTC;
1.1 root 13:
14: RTCDevice::RTCDevice()
15: {
16: // 秒への繰り上がりを許可。
17: rtc.enable_sec = true;
18: }
19:
20: RTCDevice::~RTCDevice()
21: {
22: }
23:
24: // ホストの現在時刻を rtc に取得。
25: // (派生クラスの InitRTC() から呼ばれる)
26: // localtime を内部時刻にするときは use_localtime == true
27: // UTC を内部時刻にするときは use_localtime == false にすること。
28: void
29: RTCDevice::LoadHostRTC(bool use_localtime)
30: {
31: struct timeval tv;
32: struct tm tm;
33:
34: // 起動した時の現在時刻で設定する
35: gettimeofday(&tv, NULL);
36: if (use_localtime) {
37: localtime_r(&tv.tv_sec, &tm);
38: } else {
39: gmtime_r(&tv.tv_sec, &tm);
40: }
41: // 秒未満の初期値もそれなりの精度にしておく (1000*1000 / 32 = 31250)
42: rtc.cnt = tv.tv_usec / 31250;
43: rtc.sec = tm.tm_sec;
44: rtc.min = tm.tm_min;
45: rtc.hour = tm.tm_hour;
46: // wday も tm_wday も日曜が 0
47: rtc.wday = tm.tm_wday;
48: rtc.mday = tm.tm_mday;
49: rtc.mon = tm.tm_mon + 1;
50: rtc.year = tm.tm_year + 1900;
51: }
52:
53: // 32Hz カウンタの処理。
54: // 戻り値は更新が起きた位。
55: // 派生クラスで用意した ClockIn() から呼び出すこと。
56: uint32
57: RTCDevice::CountUp()
58: {
59: uint32 updates;
60:
61: updates = 0;
62:
63: // 内部カウンタアップ
64: rtc.cnt++;
65: rtc.cnt &= 63;
66:
67: // RP5C15 の Timer Enable は内部カウンタは動作していて、
68: // 秒へのカウントアップをするかどうかのフラグ。
69: if (rtc.enable_sec == false) {
70: return updates;
71: }
72:
73: // 秒の繰り上がり処理。
74: // 32カウントで1秒だが、RP5C15 はタイマー停止中でも 1秒への繰り上がり
75: // 1回は内部で覚えているので、ここだけ 32 以上だったら 32 を引く運用。
76: if (rtc.cnt >= 32) {
77: rtc.cnt -= 32;
78: updates |= CarrySec(updates);
79: }
80: return updates;
81: }
82:
83: // 秒への繰り上がり処理。
84: // 戻り値は更新が起きた位。
85: uint32
86: RTCDevice::CarrySec(uint32 updates)
87: {
88: rtc.sec++;
89: updates |= RTCDevice::UPDATE_SEC;
90:
91: if (rtc.sec >= 60) {
92: rtc.sec = 0;
93: updates |= CarryMin(updates);
94: }
95: return updates;
96: }
97:
98: // 分への繰り上がり処理。
99: // 戻り値は更新が起きた位。
100: uint32
101: RTCDevice::CarryMin(uint32 updates)
102: {
103: rtc.min++;
104: updates |= RTCDevice::UPDATE_MIN;
105:
106: if (rtc.min >= 60) {
107: rtc.min = 0;
108: updates |= CarryHour(updates);
109: }
110: return updates;
111: }
112:
113: // 時への繰り上がり処理。時間は24時間計。
114: // 戻り値は更新が起きた位。
115: uint32
116: RTCDevice::CarryHour(uint32 updates)
117: {
118: rtc.hour++;
119: updates |= RTCDevice::UPDATE_HOUR;
120:
121: if (rtc.hour >= 24) {
122: rtc.hour = 0;
123: updates |= CarryDay(updates);
124: }
125: return updates;
126: }
127:
128: // 日への繰り上がり処理。
129: // 戻り値は更新が起きた位。
130: uint32
131: RTCDevice::CarryDay(uint32 updates)
132: {
133: // まず曜日
134: rtc.wday = (rtc.wday + 1) % 7;
135:
136: // 日にち
137: rtc.mday++;
138: updates |= RTCDevice::UPDATE_DAY;
139:
140: // 日が繰り上がった結果、月が繰り上がるかどうか
141: static const int mdays[] = {
142: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
143: };
144: if (rtc.mday > (mdays[rtc.mon] + (IsLeapMon() ? 1 : 0))) {
145: rtc.mday = 1;
146: updates |= CarryMon(updates);
147: }
148: return updates;
149: }
150:
151: // 月への繰り上がり処理。
152: // 戻り値は更新が起きた位。
153: uint32
154: RTCDevice::CarryMon(uint32 updates)
155: {
156: rtc.mon++;
157: updates |= RTCDevice::UPDATE_MON;
158:
159: if (rtc.mon >= 12) {
160: rtc.mon = 1;
161: updates |= CarryYear(updates);
162: }
163: return updates;
164: }
165:
166: // 年への繰り上がり処理。
167: // 戻り値は更新が起きた位。
168: uint32
169: RTCDevice::CarryYear(uint32 updates)
170: {
171: rtc.year++;
172: updates |= RTCDevice::UPDATE_YEAR;
173:
174: // 特にすることはない
175:
176: return updates;
177: }
178:
179: // 閏年の2月なら true を返す。
180: bool
181: RTCDevice::IsLeapMon() const
182: {
183: // 1900年から2100年までの間は 4 で割るだけでよい。
184: if ((rtc.year % 4 == 0) && (rtc.mon == 2)) {
185: return true;
186: }
187: return false;
188: }
189:
190: // 曜日文字列
191: /*static*/ const char * const
192: RTCDevice::wdays[7] = {
193: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
194: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.