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