Annotation of nono/vm/rtc.cpp, revision 1.1

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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.