|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // 電源周り
9: //
10:
11: #include "power.h"
12: #include "mainapp.h"
1.1.1.2 root 13: #include "mfp.h"
1.1 root 14: #include "scheduler.h"
1.1.1.3 root 15: #include "syncer.h"
1.1 root 16: #include "uimessage.h"
17:
1.1.1.4 root 18: //
19: // 共通クラス
20: //
21:
1.1 root 22: // コンストラクタ
23: PowerDevice::PowerDevice()
1.1.1.3 root 24: : inherited(OBJ_POWER)
1.1 root 25: {
26: }
27:
28: // デストラクタ
29: PowerDevice::~PowerDevice()
30: {
1.1.1.3 root 31: }
32:
33: // 初期化
34: bool
35: PowerDevice::Init()
36: {
37: syncer = GetSyncer();
38:
39: scheduler->ConnectMessage(MessageID::RESET, this,
1.1.1.4 root 40: ToMessageCallback(&PowerDevice::ResetMessage));
1.1.1.3 root 41: scheduler->ConnectMessage(MessageID::POWEROFF_RESTART, this,
1.1.1.4 root 42: ToMessageCallback(&PowerDevice::PowerOffMessage));
1.1.1.3 root 43: scheduler->ConnectMessage(MessageID::POWER_BUTTON, this,
1.1.1.4 root 44: ToMessageCallback(&PowerDevice::PowerButtonMessage));
1.1.1.3 root 45:
46: return true;
1.1 root 47: }
48:
1.1.1.4 root 49: // 電源ボタンを押す。 (外部から呼ばれる用)
50: void
51: PowerDevice::PushPowerButton()
52: {
53: scheduler->SendMessage(MessageID::POWER_BUTTON);
54: }
55:
1.1 root 56: // リセットをスケジューラに指示する。(外部から呼ばれる用)
57: void
58: PowerDevice::MakeResetHard()
59: {
1.1.1.3 root 60: scheduler->SendMessage(MessageID::RESET);
1.1 root 61: }
62:
63: // リスタートをスケジューラに指示する。(外部から呼ばれる用)
64: void
65: PowerDevice::MakeRestart()
66: {
1.1.1.3 root 67: scheduler->SendMessage(MessageID::POWEROFF_RESTART);
1.1 root 68: }
69:
1.1.1.4 root 70: // 電源ボタンのメッセージコールバック
1.1 root 71: void
1.1.1.4 root 72: PowerDevice::PowerButtonMessage(MessageID msgid, uint32 arg)
1.1 root 73: {
1.1.1.4 root 74: DoPowerButton();
1.1 root 75: }
76:
77: // リセットのメッセージコールバック
78: void
1.1.1.4 root 79: PowerDevice::ResetMessage(MessageID msgid, uint32 arg)
1.1 root 80: {
81: DoResetHard();
82: }
83:
84: // 電源オフのメッセージコールバック
85: void
1.1.1.4 root 86: PowerDevice::PowerOffMessage(MessageID msgid, uint32 arg)
1.1 root 87: {
88: DoPowerOff(msgid);
89: }
90:
1.1.1.4 root 91: // 電源ボタン操作。
92: // ただ電源をオンオフするだけなら共通クラスのこれが使える。
93: // そうでない場合は継承側で対応すること。
1.1.1.2 root 94: void
1.1.1.4 root 95: PowerDevice::DoPowerButton()
1.1.1.2 root 96: {
1.1.1.4 root 97: putlog(1, "PowerButton");
98:
99: if (ispower == false) {
100: DoPowerOn();
101: } else {
102: DoPowerOff(MessageID::POWEROFF_EXIT);
103: }
104:
105: // LED の状態が変わったことを UI に通知。
106: led = ispower;
107: UIMessage::Post(UIMessage::LED);
1.1.1.2 root 108: }
109:
1.1 root 110: // 電源オン操作 (Device::ResetHard ではない)
111: void
112: PowerDevice::DoPowerOn()
113: {
114: putlog(1, "PowerOn");
115:
116: if (ispower == false) {
117: // 全デバイス電源オン
118: ispower = true;
119: for (auto obj : gMainApp.GetObjects()) {
120: auto dev = dynamic_cast<Device *>(obj);
121: if (dev) {
122: dev->ResetHard(true);
123: }
124: }
125:
126: // 動作モード変更
1.1.1.3 root 127: syncer->RequestPowerOffMode(false);
1.1 root 128: }
129: }
130:
131: // リセット操作 (Device::ResetHard ではない)
132: void
133: PowerDevice::DoResetHard()
134: {
135: putlog(1, "Reset");
136:
137: if (ispower) {
138: // 全デバイスをリセット
139: for (auto obj : gMainApp.GetObjects()) {
140: auto dev = dynamic_cast<Device *>(obj);
141: if (dev) {
142: dev->ResetHard(false);
143: }
144: }
145: }
146: }
147:
148: // 電源オフ操作 (Device::PowerOff ではない)
149: void
150: PowerDevice::DoPowerOff(MessageID msgid)
151: {
152: putlog(1, "PowerOff");
153:
154: assertmsg(msgid == MessageID::POWEROFF_EXIT ||
155: msgid == MessageID::POWEROFF_RESTART,
156: "msgid=%d", (int)msgid);
157:
158: if (ispower) {
159: // 全デバイス電源オフ
160: for (auto obj : gMainApp.GetObjects()) {
161: auto dev = dynamic_cast<Device *>(obj);
162: if (dev) {
163: dev->PowerOff();
164: }
165: }
166: ispower = false;
167:
168: // 動作モード変更
1.1.1.3 root 169: syncer->RequestPowerOffMode(true);
1.1 root 170: }
171:
172: // 電源オフ後の動作は引数によって異なる
173: if (msgid == MessageID::POWEROFF_RESTART) {
174: // 時間を始め直す
1.1.1.3 root 175: scheduler->StartTime();
1.1 root 176: // 再び電源オンにする (リスタート)
177: DoPowerOn();
178: } else {
179: // そうでなければ、GUI に終了を通知
180: UIMessage::Post(UIMessage::APPEXIT);
181: }
182: }
1.1.1.2 root 183:
1.1.1.4 root 184: // 電源ボタンの状態を返す。
185: PowerButtonState
186: PowerDevice::GetPowerButtonState() const
187: {
188: if (alternate_switch) {
189: return (PowerButtonState)power_button;
190: } else {
191: return PowerButtonState::NoState;
192: }
193: }
194:
195: // システム内の電源オン信号を受け取る。
196: // 呼ぶなら継承クラス側で対応すること。
1.1.1.2 root 197: void
1.1.1.4 root 198: PowerDevice::SetSystemPowerOn(bool poweron)
1.1.1.2 root 199: {
1.1.1.5 root 200: assertmsg(false, "PowerDevice::SetSystemPowerOn should not be called.");
1.1.1.4 root 201: }
202:
203:
204: //
205: // 電源周り (LUNA)
206: //
207:
208: // LUNA はフロントのモーメンタリスイッチで電源オンにする。オフには出来ない。
209: // 電源オフは PIO1 から制御する。PIO1 の PC4 を %0 にすると 1msec 後に
210: // 電源がオフになる。PC4 を %1 にすることで電源オフを回避できる。
211: // 特に PIO のモード変更をすると PC0-7 出力が一旦 %0 になるので、
212: // 必ず間髪入れずに回避しなければならないらしい。どうして…。
213: //
214: // 電源ボタン操作 -> PowerOn
215: // PC4 を %0 -> PowerOff イベントを開始
216: // PC4 を %1 -> PowerOff イベントを停止
217:
218: // コンストラクタ
219: LunaPowerDevice::LunaPowerDevice()
220: : inherited()
221: {
222: }
223:
224: // デストラクタ
225: LunaPowerDevice::~LunaPowerDevice()
226: {
227: }
1.1.1.2 root 228:
1.1.1.5 root 229: // 初期化
230: bool
231: LunaPowerDevice::Init()
232: {
233: if (inherited::Init() == false) {
234: return false;
235: }
236:
237: event.func = ToEventCallback(&LunaPowerDevice::PowerCallback);
238: event.time = 1_msec;
239: event.SetName("Power Off");
240: scheduler->RegistEvent(event);
241:
242: return true;
243: }
244:
1.1.1.4 root 245: // PIO1 の PC4 が繋がっているということにする。
246: void
247: LunaPowerDevice::SetSystemPowerOn(bool poweron)
248: {
249: if (poweron) {
250: if (event.IsRunning()) {
251: putlog(1, "Cancel Power-Off");
252: scheduler->StopEvent(event);
253: }
1.1.1.2 root 254: } else {
1.1.1.4 root 255: if (event.IsRunning() == false) {
256: putlog(1, "Start Power-Off timer");
257: scheduler->RestartEvent(event);
258: }
1.1.1.2 root 259: }
260: }
261:
1.1.1.4 root 262: // LUNA の電源オフが信号状態の変化に対し 1msec 遅れて応答することを
263: // エミュレートするためのイベントコールバック。
264: void
265: LunaPowerDevice::PowerCallback(Event& ev)
266: {
267: DoPowerOff(MessageID::POWEROFF_EXIT);
268:
269: // LED の状態が変わったことを UI に通知。
270: led = ispower;
271: UIMessage::Post(UIMessage::LED);
272: }
273:
274:
275: //
276: // 電源周り (X680x0)
277: //
278:
279: // X68030 はフロントのオルタネートスイッチで電源オンにする。
280: // RTC 等でも電源オンは可能だが現状サポートしていないので省略。
281: //
282: // 電源オン後は以下のいずれか一つでも成り立っている間は電源オン。
283: // 1 電源ボタンがオン状態
284: // 2 ALARM_OUT がアサート
285: // 3 システムポートが電源オフコマンドを発行していない。
286:
287: // コンストラクタ
288: X68030PowerDevice::X68030PowerDevice()
289: : inherited()
290: {
291: alternate_switch = true;
292: }
293:
294: // デストラクタ
295: X68030PowerDevice::~X68030PowerDevice()
296: {
297: }
298:
299: // 電源ボタン操作
300: void
301: X68030PowerDevice::DoPowerButton()
302: {
303: putlog(1, "PowerButton");
304:
305: // X68030 の電源ボタンはオルタネート動作
306: power_button = !power_button;
307: Change();
308:
309: // MFP の POWSW 信号は負論理
310: GetMFPDevice()->SetPowSW(!power_button);
311: }
312:
1.1.1.2 root 313: // RP5C15 の ALARM_OUT を受け取る
314: void
1.1.1.4 root 315: X68030PowerDevice::SetAlarmOut(bool alarm_out_)
1.1.1.2 root 316: {
317: alarm_out = alarm_out_;
318: Change();
319: }
320:
1.1.1.4 root 321: // システムポートからの電源オフコマンド発行で false が来る。
322: // 便宜上、電源投入時にはシステムポートがこれを true にする。
1.1.1.2 root 323: void
1.1.1.4 root 324: X68030PowerDevice::SetSystemPowerOn(bool poweron)
1.1.1.2 root 325: {
326: system_poweron = poweron;
327: Change();
328: }
329:
330: // 電源状態の変更。
331: // power_button、alarm_out、system_poweron のいずれかの変更で呼ぶこと。
332: void
1.1.1.4 root 333: X68030PowerDevice::Change()
1.1.1.2 root 334: {
335: bool old_power = ispower;
336: bool new_power = power_button | alarm_out | system_poweron;
1.1.1.5 root 337: putlog(1, "Change: old=%u new=%u (button=%u alarm=%u system=%u)",
1.1.1.4 root 338: old_power, new_power, power_button, alarm_out, system_poweron);
1.1.1.2 root 339:
340: if (old_power == false && new_power) {
341: DoPowerOn();
342: } else if (old_power && new_power == false) {
1.1.1.4 root 343: DoPowerOff(MessageID::POWEROFF_EXIT);
1.1.1.2 root 344: }
345:
346: bool old_led = led;
1.1.1.4 root 347: // 電源 LED は X68030 の電源制御部の回路による。
348: led = power_button | alarm_out;
349:
1.1.1.2 root 350: if (old_led != led) {
351: // LED の状態が変わったことを UI に通知
352: UIMessage::Post(UIMessage::LED);
353: }
354: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.