--- nono/vm/sysclk.cpp 2026/04/29 17:04:53 1.1.1.8 +++ nono/vm/sysclk.cpp 2026/04/29 17:05:20 1.1.1.13 @@ -4,44 +4,75 @@ // Licensed under nono-license.txt // +// +// LUNA システムクロック +// + +// システムクロックは実時間または仮想時間のいずれかに同期するため、 +// システムクロック独自の時刻 stime を持つ。 +// stime は、割り込みを発生させるごとに、LUNA-I なら 16.67msec、 +// LUNA-88K なら 10msec 進行する。 + #include "sysclk.h" #include "config.h" #include "interrupt.h" +#include "rtc.h" +#include "scheduler.h" +#include "syncer.h" -std::unique_ptr gSysClk; - +// コンストラクタ SysClkDevice::SysClkDevice() + : inherited(OBJ_SYSCLK) { - logname = "sysclk"; - devname = "SystemClock"; - devaddr = 0x63000000; + monitor.func = ToMonitorCallback(&SysClkDevice::MonitorUpdate); + monitor.SetSize(31, 2); + monitor.Regist(ID_MONITOR_SYSCLK); - event.dev = this; - event.func = (DeviceCallback_t)&SysClkDevice::Callback; + event.func = ToEventCallback(&SysClkDevice::Callback); event.code = 0; - event.SetName("System Clock"); + event.Regist("System Clock"); } +// デストラクタ SysClkDevice::~SysClkDevice() { } +// 初期化 bool SysClkDevice::Init() { + if (inherited::Init() == false) { + return false; + } + + interrupt = GetInterruptDevice(); + // クロックは機種ごとに異なる const ConfigItem& item = gConfig->Find("!sysclk-period"); - event.time = item.AsInt(); + period = item.AsInt(); + event.time = period; + + // クロックの同期方法 + sync_rt = GetRTCDevice()->GetSyncRealtime(); + return true; } -bool -SysClkDevice::PowerOn() +// 電源オン/リセット +void +SysClkDevice::ResetHard(bool poweron) { - // 電源オンですぐ起動 - sysint = false; - event.Start(); - return true; + // XXX たぶん電源オンだけで作用する? + if (poweron) { + if (sync_rt) { + stime = GetSyncer()->GetRealTime(); + } + + // 電源オンですぐ起動 + sysint = false; + scheduler->RestartEvent(event); + } } uint64 @@ -55,9 +86,9 @@ uint64 SysClkDevice::Write(uint32 offset, uint32 data) { // 何か書き込まれたら、フラグをクリア - putlog(1, "システムクロック割り込みクリア"); + putlog(3, "Clear system clock interrupt"); sysint = false; - gInterrupt->NegateINT(this); + interrupt->NegateINT(this); return 0; } @@ -67,6 +98,19 @@ SysClkDevice::Peek(uint32 offset) return GetInt(); } +void +SysClkDevice::MonitorUpdate(Monitor *, TextScreen& screen) +{ + int y; + + screen.Clear(); + y = 0; + + int width = stime < 86400_sec ? 20 : 25; + screen.Print(0, y++, "Sync: %s", sync_rt ? "Real Time" : "Virtual Time"); + screen.Print(0, y++, "Time: %*s", width, TimeToStr(stime).c_str()); +} + // 割り込み状態を取得(?) uint8 SysClkDevice::GetInt() const @@ -83,8 +127,18 @@ SysClkDevice::GetInt() const void SysClkDevice::Callback(Event& ev) { - putlog(3, "システムクロック割り込み発生"); + putlog(3, "Interrupt occured"); + + // システムクロックとしての現在時刻。 + // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。 + stime += period; + sysint = true; - gInterrupt->AssertINT(this); - ev.Start(); + interrupt->AssertINT(this); + + if (sync_rt) { + scheduler->StartRealtimeEvent(ev, stime, period); + } else { + scheduler->StartEvent(ev); + } }