|
|
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:
1.1.1.12 root 7: //
8: // NVRAM/RTC (MK48T02)
9: //
10:
1.1 root 11: #pragma once
12:
1.1.1.14 root 13: #include "rtc.h"
1.1.1.3 root 14: #include "mappedfile.h"
1.1 root 15:
16: // MK48T02 の時計部分のレジスタと内部状態
17: struct MK48T02Clock
18: {
1.1.1.12 root 19: // MK48T02 の場合:
20: //
1.1.1.10 root 21: // b7 b6 b5 b4 b3 b2 b1 b0
22: // +----+----+----+----+----+----+----+----+
23: // 7ff | YEAR (4+4bit) | (YEAR: 00..99)
24: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 25: // 7fe | XX XX XX | MONTH (1+4bit) | (MONTH: 01..12)
1.1.1.10 root 26: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 27: // 7fd | XX XX | DATE (2+4bit) | (DATE: 01..31)
1.1.1.10 root 28: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 29: // 7fc | XX | FT | XX XX XX |WEEKDAY (3bit)| (WEEKDAY: 1..7)
1.1.1.10 root 30: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 31: // 7fb | KS | XX | HOUR (2+4bit) | (HOURS: 00..23)
1.1.1.10 root 32: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 33: // 7fa | XX | MINUTES (3+4bit) | (MINUTES: 00..59)
1.1.1.10 root 34: // +----+----+----+----+----+----+----+----+
35: // 7f9 | ST | SECONDS (3+4bit) | (SECONDS: 00..59)
36: // +----+----+----+----+----+----+----+----+
37: // 7f8 | W | R | CALIBRATION | (CONTROL)
38: // +----+----+----+----+----+----+----+----+
39: //
1.1.1.12 root 40: // 'XX' はデータシートでは '0' だが書き込んだ値が読み返せるようだ。
41: // SPARCstation2 の PROM で少なくとも +7fa の b7 はそう観測されている
42: // ように思える(Issue#75)。他のビットも全部同じ挙動をするかは確認手段
43: // が手元にないので分からないが、内部構造的にはただの SRAM が見えてそう
44: // な気もするので、とりあえずデータシートで '0' になっているところは
45: // 全てメモリとして扱うことにする。何か分かったらまた対応する。
1.1.1.11 root 46: //
47: //
1.1.1.12 root 48: // (参考までに) M48T02 の場合:
49: //
50: // 互換チップ M48T02 は、そのデータシート上 '0' のところでも、常に %0
51: // しか読み出せないところ (以下表中 '0')と、書き込んだ値が読み出せる
52: // ところ (以下表中 'XX') とがあるようだ。
53: // また機種によっては以下の位置に BLE/BE 拡張と CEB/CB 拡張がある。
54: // BLE, BL は Battery Low Enable, Battery Low。(BL は Read Only)
1.1.1.11 root 55: // CEB, CB は Century Enable Bit, Century Bit。
56: //
1.1.1.12 root 57: // b7 b6 b5 b4 b3 b2 b1 b0
58: // +----+----+----+----+----+----+----+----+
59: // 7ff | YEAR |
60: // +----+----+----+----+----+----+----+----+
61: // 7fe | 0 0 0 | MONTH |
62: // +----+----+----+----+----+----+----+----+
63: // 7fd | BLE| BL | DATE |
1.1.1.11 root 64: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 65: // 7fc | XX | FT | CEB| CB | 0 | WEEKDAY |
1.1.1.11 root 66: // +----+----+----+----+----+----+----+----+
1.1.1.12 root 67: // 7fb | KS | 0 | HOUR |
68: // +----+----+----+----+----+----+----+----+
69: // 7fa | 0 | MINUTES |
70: // +----+----+----+----+----+----+----+----+
71: // 7f9 | ST | SECONDS |
72: // +----+----+----+----+----+----+----+----+
73: // 7f8 | W | R | CALIBRATION |
1.1.1.11 root 74: // +----+----+----+----+----+----+----+----+
1.1.1.10 root 75:
76: // コントロールレジスタは全ビットを保持。
77: // ただし b5-b0 のキャリブレーションは未実装。
1.1 root 78: static const uint8 WRITE = 0x80; // WRITE BIT
79: static const uint8 READ = 0x40; // READ BIT
80:
1.1.1.16 root 81: // 内部のカウンタと毎秒ラッチされるレジスタの2ステージ構成になっている。
1.1.1.10 root 82: // ここには制御ビット部分は含まない。
83: struct calendar {
84: uint8 sec; // BCD 秒(00-59)
85: uint8 min; // BCD 分(00-59)
86: uint8 hour; // BCD 時(00-23)
87: uint8 wday; // 曜日(1-7; 7=日曜)
88: uint8 mday; // BCD 日(01-31)
89: uint8 mon; // BCD 月(01-12)
90: uint8 year; // BCD 年(00-99; 西暦年の下二桁)
91: };
92: calendar in {}; // 内部カウンタ
93:
1.1.1.16 root 94: // 秒カウンタの bit7 が STOP ビット。
1.1.1.10 root 95: static const uint8 STOP = 0x80;
1.1.1.16 root 96: // STOP 状態を保持。
1.1.1.10 root 97: uint8 stop {};
1.1 root 98:
1.1.1.16 root 99: // 時カウンタの bit7 が KICKSTART ビット。
1.1.1.10 root 100: // KICKSTART は内部発振器のスタートに使用するが、改良版である
1.1.1.16 root 101: // M48T02 (K なし)では廃止された。動作は実装しない。
1.1.1.10 root 102: static const uint8 KICKSTART = 0x80;
1.1 root 103: // KICKSTART 状態を保持
1.1.1.10 root 104: uint8 kickstart {};
1.1 root 105:
1.1.1.16 root 106: // 曜日カウンタの bit6 が Frequency Test ビット。動作は実装しない。
1.1.1.10 root 107: static const uint8 FREQTEST = 0x40;
108: // FreqTest 状態を保持
109: uint8 freqtest {};
1.1 root 110: };
111:
112: class MK48T02Device : public RTCDevice
113: {
1.1.1.3 root 114: using inherited = RTCDevice;
1.1 root 115: public:
116: MK48T02Device();
1.1.1.14 root 117: ~MK48T02Device() override;
1.1 root 118:
1.1.1.3 root 119: bool Init() override;
1.1 root 120:
1.1.1.12 root 121: void StartTime() override;
122:
1.1.1.2 root 123: // 指定したアドレスからの文字列を読み出す (内蔵 ROM からのアクセス用)
124: std::string PeekString(uint32 addr) const;
125: // 指定したアドレスに文字列を書き込む (内蔵 ROM からのアクセス用)
126: bool WriteString(uint32 addr, const std::string& data);
1.1.1.9 root 127: // 全域をゼロクリアする (内蔵 ROM からのアクセス用)
128: void ClearAll();
1.1.1.2 root 129:
1.1.1.10 root 130: // 内蔵カウンタへのアクセス。
131: // ラッチカウンタではないことに注意。
132: uint GetSec() const override; // 秒(0-59)
133: uint GetMin() const override; // 分(0-59)
134: uint GetHour() const override; // 時(0-23)
135: uint GetWday() const override; // 曜日(0が日曜)
136: uint GetMday() const override; // 日(1-31)
137: uint GetMon() const override; // 月(1-12)
138: uint GetYear() const override; // 年(西暦)
139: uint GetLeap() const override; // うるう年カウンタ(0..3)
140:
1.1.1.2 root 141: // BusIO インタフェース
1.1.1.15 root 142: // (内蔵 ROM からのアクセス用に特別に public にしてある)
143: busdata ReadPort(uint32 offset);
144: busdata WritePort(uint32 offset, uint32 data);
145: busdata PeekPort(uint32 offset);
146: protected:
1.1.1.2 root 147: static const uint32 NPORT = 2048;
1.1.1.15 root 148: bool PokePort(uint32 offset, uint32 data);
1.1.1.2 root 149:
1.1.1.10 root 150: // 仮想RTCからのクロック
151: void Tick1Hz() override;
152:
153: // 内蔵カウンタへのアクセス。
154: void SetSec(uint v) override;
155: void SetMin(uint v) override;
156: void SetHour(uint v) override;
157: void SetWday(uint v) override;
158: void SetMday(uint v) override;
159: void SetMon(uint v) override;
160: void SetYear(uint v) override;
161: void SetLeap(uint v) override;
162:
1.1 root 163: private:
164: // バイナリ <-> BCD 変換
165: static inline uint8 num2BCD(uint8);
166: static inline uint8 BCD2num(uint8);
167:
1.1.1.10 root 168: // 年のデコード。
169: uint DecodeYear(uint bcd_year) const;
170:
1.1 root 171: // コントロールレジスタへの書き込み
172: void WriteCtrl(uint32 data);
173:
1.1.1.12 root 174: // NVRAM からカレンダへロード
175: MK48T02Clock::calendar Load() const;
176:
177: // カレンダを NVRAM にストア
178: void Store(const MK48T02Clock::calendar& cal);
179:
1.1.1.17! root 180: DECLARE_MONITOR_SCREEN(MonitorScreen);
1.1.1.9 root 181:
1.1.1.3 root 182: // ファイル
1.1 root 183: std::string filename {};
1.1.1.3 root 184: MappedFile file {};
185: uint8 *mem {};
1.1 root 186:
187: // 時計
188: MK48T02Clock reg {};
189:
1.1.1.10 root 190: // うるう年補正量
191: uint adjust_leap {};
192:
193: // 外部レジスタをホールド(更新停止)しているときは true
194: bool hold {};
1.1.1.9 root 195:
1.1.1.16 root 196: Monitor *monitor {};
1.1 root 197: };
1.1.1.13 root 198:
1.1.1.17! root 199: inline MK48T02Device *GetMK48T02Device() {
1.1.1.13 root 200: return Object::GetObject<MK48T02Device>(OBJ_RTC);
201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.