--- nono/vm/power.cpp 2026/04/29 17:05:09 1.1.1.1 +++ nono/vm/power.cpp 2026/04/29 17:05:17 1.1.1.3 @@ -10,75 +10,64 @@ #include "power.h" #include "mainapp.h" +#include "mfp.h" #include "scheduler.h" -#include "sync.h" +#include "syncer.h" #include "uimessage.h" -// グローバル参照用 -PowerDevice *gPower; - // コンストラクタ PowerDevice::PowerDevice() - : inherited("Power") + : inherited(OBJ_POWER) { - gScheduler->ConnectMessage(MessageID::POWERON, this, - ToMessageCallback(&PowerDevice::PowerOnCallback)); - gScheduler->ConnectMessage(MessageID::RESET, this, - ToMessageCallback(&PowerDevice::ResetCallback)); - gScheduler->ConnectMessage(MessageID::POWEROFF_EXIT, this, - ToMessageCallback(&PowerDevice::PowerOffCallback)); - gScheduler->ConnectMessage(MessageID::POWEROFF_RESTART, this, - ToMessageCallback(&PowerDevice::PowerOffCallback)); + event.func = ToEventCallback(&PowerDevice::PowerCallback); + event.time = 1_msec; + event.Regist("Power Off"); } // デストラクタ PowerDevice::~PowerDevice() { - gPower = NULL; } // 初期化 bool PowerDevice::Init() { - // 初期状態は電源オフ - ispower = false; - return true; -} + if (inherited::Init() == false) { + return false; + } -// 電源オンをスケジューラに指示する。(外部から呼ばれる用) -void -PowerDevice::MakePowerOn() -{ - gScheduler->SendMessage(MessageID::POWERON); + syncer = GetSyncer(); + + scheduler->ConnectMessage(MessageID::RESET, this, + ToMessageCallback(&PowerDevice::ResetCallback)); + scheduler->ConnectMessage(MessageID::POWEROFF_RESTART, this, + ToMessageCallback(&PowerDevice::PowerOffCallback)); + scheduler->ConnectMessage(MessageID::POWER_BUTTON, this, + ToMessageCallback(&PowerDevice::PowerButtonCallback)); + + return true; } // リセットをスケジューラに指示する。(外部から呼ばれる用) void PowerDevice::MakeResetHard() { - gScheduler->SendMessage(MessageID::RESET); -} - -// 電源オフ後終了をスケジューラに指示する。(外部から呼ばれる用) -void -PowerDevice::MakePowerOffExit() -{ - gScheduler->SendMessage(MessageID::POWEROFF_EXIT); + scheduler->SendMessage(MessageID::RESET); } // リスタートをスケジューラに指示する。(外部から呼ばれる用) void PowerDevice::MakeRestart() { - gScheduler->SendMessage(MessageID::POWEROFF_RESTART); + scheduler->SendMessage(MessageID::POWEROFF_RESTART); } -// 電源オンのメッセージコールバック +// 電源ボタンを押す。 (外部から呼ばれる用) void -PowerDevice::PowerOnCallback(MessageID msgid, uint32 arg) +PowerDevice::PowerButton() { - DoPowerOn(); + scheduler->SendMessage(MessageID::POWER_BUTTON); } // リセットのメッセージコールバック @@ -95,6 +84,13 @@ PowerDevice::PowerOffCallback(MessageID DoPowerOff(msgid); } +// 電源ボタンのメッセージコールバック +void +PowerDevice::PowerButtonCallback(MessageID msgid, uint32 arg) +{ + DoPowerButton(); +} + // 電源オン操作 (Device::ResetHard ではない) void PowerDevice::DoPowerOn() @@ -112,7 +108,7 @@ PowerDevice::DoPowerOn() } // 動作モード変更 - gSync->RequestPowerOffMode(false); + syncer->RequestPowerOffMode(false); } } @@ -154,13 +150,13 @@ PowerDevice::DoPowerOff(MessageID msgid) ispower = false; // 動作モード変更 - gSync->RequestPowerOffMode(true); + syncer->RequestPowerOffMode(true); } // 電源オフ後の動作は引数によって異なる if (msgid == MessageID::POWEROFF_RESTART) { // 時間を始め直す - gScheduler->StartTime(); + scheduler->StartTime(); // 再び電源オンにする (リスタート) DoPowerOn(); } else { @@ -168,3 +164,84 @@ PowerDevice::DoPowerOff(MessageID msgid) UIMessage::Post(UIMessage::APPEXIT); } } + +// 電源ボタン操作 +void +PowerDevice::DoPowerButton() +{ + putlog(1, "PowerButton"); + + if (gMainApp.IsX68030()) { + // X68030 の電源ボタンはオルタネート動作 + power_button = !power_button; + Change(); + // MFP の POWSW 信号は負論理 + GetMFPDevice()->SetPowSW(!power_button); + } else { + // LUNA の電源ボタンはモーメンタリ動作 + power_button = true; + Change(); + power_button = false; + } +} + +// RP5C15 の ALARM_OUT を受け取る +void +PowerDevice::SetAlarmOut(bool alarm_out_) +{ + alarm_out = alarm_out_; + Change(); +} + +// システム内の電源オン信号を受け取る。 +// __ +// X68030 だと PW ON/OFF 信号(の反転)、 +// LUNA だと PIO1 の POWF* 信号で、どちらの場合も true がオン。 +void +PowerDevice::SetSystemPowerOn(bool poweron) +{ + system_poweron = poweron; + Change(); +} + +// 電源状態の変更。 +// power_button、alarm_out、system_poweron のいずれかの変更で呼ぶこと。 +void +PowerDevice::Change() +{ + bool old_power = ispower; + bool new_power = power_button | alarm_out | system_poweron; + + if (old_power == false && new_power) { + DoPowerOn(); + } else if (old_power && new_power == false) { + if (gMainApp.IsX68030()) { + DoPowerOff(MessageID::POWEROFF_EXIT); + } else { + scheduler->RestartEvent(event); + } + } + + bool old_led = led; + if (gMainApp.GetVMType() == VMType::X68030) { + // X68030 の電源制御部の回路による。 + led = power_button | alarm_out; + } else { + // LUNA の場合は電源の状態そのまま? + led = ispower; + } + if (old_led != led) { + // LED の状態が変わったことを UI に通知 + UIMessage::Post(UIMessage::LED); + } +} + +// LUNA の電源オフが信号状態の変化に対し 1msec 遅れて応答することを +// エミュレートするためのイベントコールバック +void +PowerDevice::PowerCallback(Event& ev) +{ + if (system_poweron == false) { + DoPowerOff(MessageID::POWEROFF_EXIT); + } +}