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