|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2017 [email protected] ! 4: // ! 5: ! 6: #include "rtc.h" ! 7: #include <sys/time.h> ! 8: ! 9: // XXX rtc の読み書きはロックしたほうがいいような気がする ! 10: ! 11: RTCDevice *gRTC; ! 12: ! 13: RTCDevice::RTCDevice() ! 14: { ! 15: rtc = (RTC){}; ! 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.