|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.10 root 7: //
8: // LUNA システムクロック
9: //
10:
1.1.1.9 root 11: // システムクロックは実時間または仮想時間のいずれかに同期するため、
12: // システムクロック独自の時刻 stime を持つ。
13: // stime は、割り込みを発生させるごとに、LUNA-I なら 16.67msec、
1.1.1.12 root 14: // LUNA-88K なら 10msec 進行する。
1.1.1.9 root 15:
1.1 root 16: #include "sysclk.h"
1.1.1.6 root 17: #include "config.h"
18: #include "interrupt.h"
1.1.1.16! root 19: #include "monitor.h"
1.1.1.10 root 20: #include "rtc.h"
21: #include "scheduler.h"
1.1.1.12 root 22: #include "syncer.h"
1.1 root 23:
1.1.1.10 root 24: // コンストラクタ
1.1 root 25: SysClkDevice::SysClkDevice()
1.1.1.12 root 26: : inherited(OBJ_SYSCLK)
1.1 root 27: {
1.1.1.16! root 28: monitor = gMonitorManager->Regist(ID_MONITOR_SYSCLK, this);
! 29: monitor->func = ToMonitorCallback(&SysClkDevice::MonitorUpdate);
! 30: monitor->SetSize(31, 3);
1.1 root 31: }
32:
1.1.1.10 root 33: // デストラクタ
1.1 root 34: SysClkDevice::~SysClkDevice()
35: {
36: }
37:
1.1.1.12 root 38: // 初期化
1.1 root 39: bool
1.1.1.4 root 40: SysClkDevice::Init()
41: {
1.1.1.12 root 42: if (inherited::Init() == false) {
43: return false;
44: }
45:
46: interrupt = GetInterruptDevice();
47:
1.1.1.4 root 48: // クロックは機種ごとに異なる
1.1.1.14 root 49: const ConfigItem& item = gConfig->Find("!sysclk-freq");
50: freq = item.AsInt();
51: period = 1_sec / freq;
1.1.1.9 root 52: event.time = period;
53:
54: // クロックの同期方法
1.1.1.12 root 55: sync_rt = GetRTCDevice()->GetSyncRealtime();
1.1.1.9 root 56:
1.1.1.15 root 57: event.func = ToEventCallback(&SysClkDevice::Callback);
58: event.code = 0;
59: event.SetName("System Clock");
60: scheduler->RegistEvent(event);
61:
1.1.1.4 root 62: return true;
63: }
64:
1.1.1.10 root 65: // 電源オン/リセット
66: void
67: SysClkDevice::ResetHard(bool poweron)
1.1 root 68: {
1.1.1.10 root 69: // XXX たぶん電源オンだけで作用する?
70: if (poweron) {
71: if (sync_rt) {
1.1.1.12 root 72: stime = GetSyncer()->GetRealTime();
1.1.1.10 root 73: }
74:
75: // 電源オンですぐ起動
1.1.1.12 root 76: scheduler->RestartEvent(event);
1.1.1.9 root 77: }
1.1.1.14 root 78:
79: // さすがに割り込みネゲートくらいするよな?
80: sysint = false;
81: ChangeInterrupt();
1.1 root 82: }
83:
1.1.1.14 root 84: busdata
1.1.1.15 root 85: SysClkDevice::ReadPort(uint32 offset)
1.1 root 86: {
1.1.1.3 root 87: // 1 ポートしかない
1.1.1.15 root 88: busdata data = GetInt();
89: data |= BusData::Size1;
90: return data;
1.1.1.3 root 91: }
1.1 root 92:
1.1.1.14 root 93: busdata
1.1.1.15 root 94: SysClkDevice::WritePort(uint32 offset, uint32 data)
1.1.1.3 root 95: {
96: // 何か書き込まれたら、フラグをクリア
1.1.1.11 root 97: putlog(3, "Clear system clock interrupt");
1.1.1.6 root 98: sysint = false;
1.1.1.14 root 99: ChangeInterrupt();
1.1.1.15 root 100:
101: busdata r = BusData::Size1;
102: return r;
1.1 root 103: }
104:
1.1.1.14 root 105: busdata
1.1.1.15 root 106: SysClkDevice::PeekPort(uint32 offset)
1.1 root 107: {
1.1.1.3 root 108: return GetInt();
109: }
110:
1.1.1.15 root 111: bool
112: SysClkDevice::PokePort(uint32 offset, uint32 data)
113: {
114: return false;
115: }
116:
1.1.1.9 root 117: void
118: SysClkDevice::MonitorUpdate(Monitor *, TextScreen& screen)
119: {
120: int y;
121:
122: screen.Clear();
123: y = 0;
124:
125: int width = stime < 86400_sec ? 20 : 25;
1.1.1.15 root 126: screen.Print(0, y++, "Freq: %u Hz", freq);
1.1.1.9 root 127: screen.Print(0, y++, "Sync: %s", sync_rt ? "Real Time" : "Virtual Time");
128: screen.Print(0, y++, "Time: %*s", width, TimeToStr(stime).c_str());
129: }
130:
1.1.1.3 root 131: // 割り込み状態を取得(?)
132: uint8
133: SysClkDevice::GetInt() const
134: {
135: uint8 data = 0;
1.1 root 136:
1.1.1.3 root 137: if (sysint) {
138: data |= 0x80;
1.1 root 139: }
1.1.1.3 root 140: return data;
1.1 root 141: }
142:
143: // イベントハンドラ
144: void
1.1.1.5 root 145: SysClkDevice::Callback(Event& ev)
1.1 root 146: {
1.1.1.11 root 147: putlog(3, "Interrupt occured");
1.1.1.9 root 148:
149: // システムクロックとしての現在時刻。
1.1.1.10 root 150: // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。
1.1.1.9 root 151: stime += period;
152:
1.1.1.10 root 153: sysint = true;
1.1.1.14 root 154: ChangeInterrupt();
1.1.1.9 root 155:
1.1.1.10 root 156: if (sync_rt) {
1.1.1.12 root 157: scheduler->StartRealtimeEvent(ev, stime, period);
1.1.1.9 root 158: } else {
1.1.1.12 root 159: scheduler->StartEvent(ev);
1.1.1.9 root 160: }
1.1 root 161: }
1.1.1.14 root 162:
163: // 割り込み信号線の状態を変える。
164: void
165: SysClkDevice::ChangeInterrupt()
166: {
167: interrupt->ChangeINT(this, sysint);
168: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.