|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // 実時間同期
9: //
10:
11: #pragma once
12:
13: #include "event.h"
14: #include "fixedqueue.h"
15: #include "message.h"
16: #include "monitor.h"
17: #include "stopwatch.h"
18:
1.1.1.3 ! root 19: class MPU680x0Device;
! 20:
1.1 root 21: class Syncer : public Device
22: {
23: using inherited = Device;
24:
25: public:
26: // 動作モード
27: // 動作モード変数 (mode) はスケジューラの走行状態を表している。以下の
28: // ビットがすべて %0 なら高速モード、どれかでも %1 なら通常モードになる。
29: //
30: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
31: // mode | |POFF|KEY |BOOT|SYNC| CPUSTAT |
32: // | | | | +---+---- CPU の状態
33: // | | | +-------------- 高速モード抑制
34: // | | +------------------- ブートページ実行中
35: // | +------------------------ キー入力中
36: // +----------------------------- 電源オフ
37: //
38: // bit1,0 (CPUSTAT) は CPU の状態を示す。%00 の時だけ高速走行が可能。
39: // これは RequestCPUMode() の引数で指定する。
40: // b1 b0
41: // 0 0 通常状態
42: // 0 1 STOP 状態 (m88k なら擬似 STOP 状態)
43: // 1 0 HALT 状態 (ダブルバスフォールト)
44: // 1 1 HALT 状態だがこちらのビットパターンは使わない
45:
46: static const uint32 SCHED_CPU_STOP = 0x0001; // CPU が STOP 状態
47: static const uint32 SCHED_CPU_HALT = 0x0002; // CPU が HALT 状態
48: static const uint32 SCHED_SYNC = 0x0004; // 高速モード抑制指示(UI)
49: static const uint32 SCHED_BOOT = 0x0008; // ブートページ実行中
50: static const uint32 SCHED_KEY = 0x0010; // キー入力中
51: static const uint32 SCHED_POWEROFF = 0x0020; // 電源オフ
52:
53: // 便宜上用意しておく
54: static const uint32 SCHED_CPU_NORMAL= 0x0000; // CPU が通常状態
55: static const uint32 SCHED_CPU_MASK = (SCHED_CPU_STOP | SCHED_CPU_HALT);
56:
57: public:
58: Syncer();
59: ~Syncer() override;
60:
61: bool Init() override;
62:
63: void StartTime(); // 時間の始まり
64:
65: void StartRealTime(); // 実時間を再開
66: void StopRealTime(); // 実時間を停止
67:
68: uint64 GetRealTime() const { return rtime; }
69:
70: // 現在の実行モードを返す。
71: uint32 GetRunMode() const { return mode; }
72:
73: // CPU 状態変更を指示する。
74: void RequestCPUMode(uint32 mode_);
75:
76: // 高速モード(UIによる指示)なら true を返す。
77: // ここでいう高速モードは STOP 状態中でも高速モード。
78: bool GetFullSpeed() const { return ((mode & SCHED_SYNC) == 0); }
79:
80: // 高速モードを指示する。
81: // true なら高速モード、false なら同期モード。
82: void RequestFullSpeed(bool enable);
83:
84: // ブートページモードの変更を指示する。
85: void RequestBootPageMode(bool isrom);
86:
87: // キー入力状態の変更を指示する。
88: void RequestKeyPressed(bool pressed);
89:
90: // 電源オフの状態の変更を指示する。オフになったとき true。
91: void RequestPowerOffMode(bool poweroff);
92:
93: // パフォーマンス測定用に実時間をログ出力
94: void PutlogRealtime();
95:
96: // パフォーマンスカウンタの値取得 (UI 表示用)
1.1.1.3 ! root 97: uint GetPerfCounter() const { return perf_counter; }
1.1 root 98:
99: // モニタ更新の下請け
100: int MonitorUpdateSub(TextScreen& screen, uint64 vtime);
101:
102: private:
103: void ChangeMode(uint32 newmode);
104:
105: // 同期イベント
106: void SyncCallback(Event& ev);
107:
108: // 動作モード変更メッセージ
1.1.1.2 root 109: void ChangeModeMessage(MessageID, uint32);
1.1 root 110:
111: // 同期処理
112: void DoSync();
113:
114: void CalcPerf();
115:
116: // スケジューラの動作モード。SCHED_*
117: uint32 mode {};
118:
119: // 実時間の基準となるストップウォッチ
120: Stopwatch realtime {};
121:
122: // 同期した時点の実経過時間
123: uint64 rtime {};
124:
125: // 同期調整用
126: uint64 rtime_epoch {};
127: uint64 vtime_epoch {};
128:
129: // sleep しすぎた時間の最大値
130: uint64 overslept {};
131:
132: // 同期回数
133: uint sync_count {}; // 現在の1秒間での同期回数
134: uint last_sync_count {}; // 前回の1秒間での同期回数
135:
136: // パフォーマンスカウンタ
137: // perfq が移動平均用のバッファ。四捨五入用に10倍値を持っておく
138: // (100% なら 1000)。perf_counter は perfq から求めた実行率で
139: // 小数以下を四捨五入する (のでこっちは 100% なら 100)。
1.1.1.3 ! root 140: uint perf_counter {}; // 実行率 [%]
1.1 root 141: FixedQueue<uint32, 3> perfq {}; // 移動平均用のバッファ
142: uint64 next_perf_rtime {}; // 次回測定予定の実経過時間
143: uint64 last_perf_rtime {}; // 前回測定時の実経過時間
144: uint64 last_perf_vtime {}; // 前回測定時の仮想経過時間
145:
1.1.1.3 ! root 146: MPU680x0Device *mpu680x0 {};
! 147:
1.1 root 148: // 同期イベント
149: Event sync_event { this };
150: };
151:
152: static inline Syncer *GetSyncer() {
153: return Object::GetObject<Syncer>(OBJ_SYNCER);
154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.