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

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

unix.superglobalmegacorp.com

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