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

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

unix.superglobalmegacorp.com

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