--- nono/vm/mk48t02.h 2026/04/29 17:04:50 1.1.1.7 +++ nono/vm/mk48t02.h 2026/04/29 17:04:59 1.1.1.10 @@ -8,45 +8,71 @@ #include "device.h" #include "mappedfile.h" +#include "monitor.h" #include "rtc.h" // MK48T02 の時計部分のレジスタと内部状態 struct MK48T02Clock { - // コントロールレジスタは以下の3つを保持。 + // b7 b6 b5 b4 b3 b2 b1 b0 + // +----+----+----+----+----+----+----+----+ + // 7ff | YEAR (4+4bit) | (YEAR: 00..99) + // +----+----+----+----+----+----+----+----+ + // 7fe | 0 0 0 | MONTH (1+4bit) | (MONTH: 01..12) + // +----+----+----+----+----+----+----+----+ + // 7fd | XX | 0 | DATE (2+4bit) | (DATE: 01..31) + // +----+----+----+----+----+----+----+----+ + // 7fc | XX | FT | XX XX | 0 |WEEKDAY (3bit)| (WEEKDAY: 1..7) + // +----+----+----+----+----+----+----+----+ + // 7fb | KS | 0 | HOUR (2+4bit) | (HOURS: 00..23) + // +----+----+----+----+----+----+----+----+ + // 7fa | 0 | MINUTES (3+4bit) | (MINUTES: 00..59) + // +----+----+----+----+----+----+----+----+ + // 7f9 | ST | SECONDS (3+4bit) | (SECONDS: 00..59) + // +----+----+----+----+----+----+----+----+ + // 7f8 | W | R | CALIBRATION | (CONTROL) + // +----+----+----+----+----+----+----+----+ + // + // '0' はデータシートでは '0' で、実際書き込んでも '0' になる。 + // 'XX' はデータシートでは '0' だが '1' が書き込める。 + + // コントロールレジスタは全ビットを保持。 + // ただし b5-b0 のキャリブレーションは未実装。 uint8 ctrl; static const uint8 WRITE = 0x80; // WRITE BIT static const uint8 READ = 0x40; // READ BIT - static const uint8 SIGN = 0x20; // SIGN BIT (?) - // 秒カウンタ(BCD) - uint8 sec; + // 内部のカウンタと毎秒ラッチされるレジスタの2ステージ構成になっている + // ここには制御ビット部分は含まない。 + struct calendar { + uint8 sec; // BCD 秒(00-59) + uint8 min; // BCD 分(00-59) + uint8 hour; // BCD 時(00-23) + uint8 wday; // 曜日(1-7; 7=日曜) + uint8 mday; // BCD 日(01-31) + uint8 mon; // BCD 月(01-12) + uint8 year; // BCD 年(00-99; 西暦年の下二桁) + }; + calendar in {}; // 内部カウンタ + calendar ex {}; // 外部レジスタ + // 秒カウンタの bit7 が STOP ビット - static const uint8 STOP = 0x80; + static const uint8 STOP = 0x80; // STOP 状態を保持 - bool stop; - - // 分カウンタ(BCD) - uint8 min; + uint8 stop {}; - // 時カウンタ(BCD) - uint8 hour; // 時カウンタの bit7 が KICKSTART ビット - static const uint8 KICKSTART = 0x80; + // KICKSTART は内部発振器のスタートに使用するが、改良版である + // M48T02 (K なし)では廃止された。動作は実装しない。 + static const uint8 KICKSTART = 0x80; // KICKSTART 状態を保持 - bool kickstart; + uint8 kickstart {}; - // 曜日カウンタ - uint8 wday; - static const uint8 FREQTEST = 0x40; // Frequency Test (未実装) - - // 日カウンタ - uint8 mday; - // 月カウンタ - uint8 mon; - // 年カウンタ (0 が 1970年) - uint8 year; - static const int YEAR_EPOCH = 1970; + // 曜日カウンタの bit6 が Frequency Test ビット + // 動作は実装しない。 + static const uint8 FREQTEST = 0x40; + // FreqTest 状態を保持 + uint8 freqtest {}; }; class MK48T02Device : public RTCDevice @@ -57,16 +83,13 @@ class MK48T02Device : public RTCDevice virtual ~MK48T02Device() override; bool Init() override; - bool InitRTC() override; - - void MonitorUpdate(TextScreen&) override; - - void ClockIn() override; // 指定したアドレスからの文字列を読み出す (内蔵 ROM からのアクセス用) std::string PeekString(uint32 addr) const; // 指定したアドレスに文字列を書き込む (内蔵 ROM からのアクセス用) bool WriteString(uint32 addr, const std::string& data); + // 全域をゼロクリアする (内蔵 ROM からのアクセス用) + void ClearAll(); // BusIO インタフェース // (内蔵 ROM からのアクセス用に特別に public にしてある) @@ -74,18 +97,47 @@ class MK48T02Device : public RTCDevice uint64 Write(uint32 offset, uint32 data); uint64 Peek(uint32 offset); + // 内蔵カウンタへのアクセス。 + // ラッチカウンタではないことに注意。 + uint GetSec() const override; // 秒(0-59) + uint GetMin() const override; // 分(0-59) + uint GetHour() const override; // 時(0-23) + uint GetWday() const override; // 曜日(0が日曜) + uint GetMday() const override; // 日(1-31) + uint GetMon() const override; // 月(1-12) + uint GetYear() const override; // 年(西暦) + uint GetLeap() const override; // うるう年カウンタ(0..3) + protected: // BusIO インタフェース static const uint32 NPORT = 2048; + // 仮想RTCからのクロック + void Tick1Hz() override; + + // 内蔵カウンタへのアクセス。 + void SetSec(uint v) override; + void SetMin(uint v) override; + void SetHour(uint v) override; + void SetWday(uint v) override; + void SetMday(uint v) override; + void SetMon(uint v) override; + void SetYear(uint v) override; + void SetLeap(uint v) override; + private: // バイナリ <-> BCD 変換 static inline uint8 num2BCD(uint8); static inline uint8 BCD2num(uint8); + // 年のデコード。 + uint DecodeYear(uint bcd_year) const; + // コントロールレジスタへの書き込み void WriteCtrl(uint32 data); + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + // ファイル std::string filename {}; MappedFile file {}; @@ -94,8 +146,11 @@ class MK48T02Device : public RTCDevice // 時計 MK48T02Clock reg {}; - // レジスタとして読める値を定数にすることで、仮想マシン状態を - // 常に同じ状態にするためのパフォーマンス測定用フラグ。 - // なお NVRAM 部分は影響されない。 - bool force_fixed {}; + // うるう年補正量 + uint adjust_leap {}; + + // 外部レジスタをホールド(更新停止)しているときは true + bool hold {}; + + Monitor monitor { this }; };