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