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