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