|
|
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:
18: // コンストラクタ
19: PowerDevice::PowerDevice()
1.1.1.3 ! root 20: : inherited(OBJ_POWER)
1.1 root 21: {
1.1.1.2 root 22: event.func = ToEventCallback(&PowerDevice::PowerCallback);
23: event.time = 1_msec;
24: event.Regist("Power Off");
1.1 root 25: }
26:
27: // デストラクタ
28: PowerDevice::~PowerDevice()
29: {
1.1.1.3 ! root 30: }
! 31:
! 32: // 初期化
! 33: bool
! 34: PowerDevice::Init()
! 35: {
! 36: if (inherited::Init() == false) {
! 37: return false;
! 38: }
! 39:
! 40: syncer = GetSyncer();
! 41:
! 42: scheduler->ConnectMessage(MessageID::RESET, this,
! 43: ToMessageCallback(&PowerDevice::ResetCallback));
! 44: scheduler->ConnectMessage(MessageID::POWEROFF_RESTART, this,
! 45: ToMessageCallback(&PowerDevice::PowerOffCallback));
! 46: scheduler->ConnectMessage(MessageID::POWER_BUTTON, this,
! 47: ToMessageCallback(&PowerDevice::PowerButtonCallback));
! 48:
! 49: return true;
1.1 root 50: }
51:
52: // リセットをスケジューラに指示する。(外部から呼ばれる用)
53: void
54: PowerDevice::MakeResetHard()
55: {
1.1.1.3 ! root 56: scheduler->SendMessage(MessageID::RESET);
1.1 root 57: }
58:
59: // リスタートをスケジューラに指示する。(外部から呼ばれる用)
60: void
61: PowerDevice::MakeRestart()
62: {
1.1.1.3 ! root 63: scheduler->SendMessage(MessageID::POWEROFF_RESTART);
1.1 root 64: }
65:
1.1.1.2 root 66: // 電源ボタンを押す。 (外部から呼ばれる用)
1.1 root 67: void
1.1.1.2 root 68: PowerDevice::PowerButton()
1.1 root 69: {
1.1.1.3 ! root 70: scheduler->SendMessage(MessageID::POWER_BUTTON);
1.1 root 71: }
72:
73: // リセットのメッセージコールバック
74: void
75: PowerDevice::ResetCallback(MessageID msgid, uint32 arg)
76: {
77: DoResetHard();
78: }
79:
80: // 電源オフのメッセージコールバック
81: void
82: PowerDevice::PowerOffCallback(MessageID msgid, uint32 arg)
83: {
84: DoPowerOff(msgid);
85: }
86:
1.1.1.2 root 87: // 電源ボタンのメッセージコールバック
88: void
89: PowerDevice::PowerButtonCallback(MessageID msgid, uint32 arg)
90: {
91: DoPowerButton();
92: }
93:
1.1 root 94: // 電源オン操作 (Device::ResetHard ではない)
95: void
96: PowerDevice::DoPowerOn()
97: {
98: putlog(1, "PowerOn");
99:
100: if (ispower == false) {
101: // 全デバイス電源オン
102: ispower = true;
103: for (auto obj : gMainApp.GetObjects()) {
104: auto dev = dynamic_cast<Device *>(obj);
105: if (dev) {
106: dev->ResetHard(true);
107: }
108: }
109:
110: // 動作モード変更
1.1.1.3 ! root 111: syncer->RequestPowerOffMode(false);
1.1 root 112: }
113: }
114:
115: // リセット操作 (Device::ResetHard ではない)
116: void
117: PowerDevice::DoResetHard()
118: {
119: putlog(1, "Reset");
120:
121: if (ispower) {
122: // 全デバイスをリセット
123: for (auto obj : gMainApp.GetObjects()) {
124: auto dev = dynamic_cast<Device *>(obj);
125: if (dev) {
126: dev->ResetHard(false);
127: }
128: }
129: }
130: }
131:
132: // 電源オフ操作 (Device::PowerOff ではない)
133: void
134: PowerDevice::DoPowerOff(MessageID msgid)
135: {
136: putlog(1, "PowerOff");
137:
138: assertmsg(msgid == MessageID::POWEROFF_EXIT ||
139: msgid == MessageID::POWEROFF_RESTART,
140: "msgid=%d", (int)msgid);
141:
142: if (ispower) {
143: // 全デバイス電源オフ
144: for (auto obj : gMainApp.GetObjects()) {
145: auto dev = dynamic_cast<Device *>(obj);
146: if (dev) {
147: dev->PowerOff();
148: }
149: }
150: ispower = false;
151:
152: // 動作モード変更
1.1.1.3 ! root 153: syncer->RequestPowerOffMode(true);
1.1 root 154: }
155:
156: // 電源オフ後の動作は引数によって異なる
157: if (msgid == MessageID::POWEROFF_RESTART) {
158: // 時間を始め直す
1.1.1.3 ! root 159: scheduler->StartTime();
1.1 root 160: // 再び電源オンにする (リスタート)
161: DoPowerOn();
162: } else {
163: // そうでなければ、GUI に終了を通知
164: UIMessage::Post(UIMessage::APPEXIT);
165: }
166: }
1.1.1.2 root 167:
168: // 電源ボタン操作
169: void
170: PowerDevice::DoPowerButton()
171: {
172: putlog(1, "PowerButton");
173:
1.1.1.3 ! root 174: if (gMainApp.IsX68030()) {
1.1.1.2 root 175: // X68030 の電源ボタンはオルタネート動作
176: power_button = !power_button;
177: Change();
178: // MFP の POWSW 信号は負論理
1.1.1.3 ! root 179: GetMFPDevice()->SetPowSW(!power_button);
1.1.1.2 root 180: } else {
181: // LUNA の電源ボタンはモーメンタリ動作
182: power_button = true;
183: Change();
184: power_button = false;
185: }
186: }
187:
188: // RP5C15 の ALARM_OUT を受け取る
189: void
190: PowerDevice::SetAlarmOut(bool alarm_out_)
191: {
192: alarm_out = alarm_out_;
193: Change();
194: }
195:
196: // システム内の電源オン信号を受け取る。
197: // __
198: // X68030 だと PW ON/OFF 信号(の反転)、
199: // LUNA だと PIO1 の POWF* 信号で、どちらの場合も true がオン。
200: void
201: PowerDevice::SetSystemPowerOn(bool poweron)
202: {
203: system_poweron = poweron;
204: Change();
205: }
206:
207: // 電源状態の変更。
208: // power_button、alarm_out、system_poweron のいずれかの変更で呼ぶこと。
209: void
210: PowerDevice::Change()
211: {
212: bool old_power = ispower;
213: bool new_power = power_button | alarm_out | system_poweron;
214:
215: if (old_power == false && new_power) {
216: DoPowerOn();
217: } else if (old_power && new_power == false) {
1.1.1.3 ! root 218: if (gMainApp.IsX68030()) {
1.1.1.2 root 219: DoPowerOff(MessageID::POWEROFF_EXIT);
220: } else {
1.1.1.3 ! root 221: scheduler->RestartEvent(event);
1.1.1.2 root 222: }
223: }
224:
225: bool old_led = led;
226: if (gMainApp.GetVMType() == VMType::X68030) {
227: // X68030 の電源制御部の回路による。
228: led = power_button | alarm_out;
229: } else {
230: // LUNA の場合は電源の状態そのまま?
231: led = ispower;
232: }
233: if (old_led != led) {
234: // LED の状態が変わったことを UI に通知
235: UIMessage::Post(UIMessage::LED);
236: }
237: }
238:
239: // LUNA の電源オフが信号状態の変化に対し 1msec 遅れて応答することを
240: // エミュレートするためのイベントコールバック
241: void
242: PowerDevice::PowerCallback(Event& ev)
243: {
244: if (system_poweron == false) {
245: DoPowerOff(MessageID::POWEROFF_EXIT);
246: }
247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.