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

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

unix.superglobalmegacorp.com

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