--- nono/vm/power.cpp 2026/04/29 17:05:09 1.1.1.1 +++ nono/vm/power.cpp 2026/04/29 17:05:13 1.1.1.2 @@ -10,6 +10,7 @@ #include "power.h" #include "mainapp.h" +#include "mfp.h" #include "scheduler.h" #include "sync.h" #include "uimessage.h" @@ -21,14 +22,16 @@ PowerDevice *gPower; PowerDevice::PowerDevice() : inherited("Power") { - gScheduler->ConnectMessage(MessageID::POWERON, this, - ToMessageCallback(&PowerDevice::PowerOnCallback)); + event.func = ToEventCallback(&PowerDevice::PowerCallback); + event.time = 1_msec; + event.Regist("Power Off"); + 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)); + gScheduler->ConnectMessage(MessageID::POWER_BUTTON, this, + ToMessageCallback(&PowerDevice::PowerButtonCallback)); } // デストラクタ @@ -37,22 +40,6 @@ PowerDevice::~PowerDevice() gPower = NULL; } -// 初期化 -bool -PowerDevice::Init() -{ - // 初期状態は電源オフ - ispower = false; - return true; -} - -// 電源オンをスケジューラに指示する。(外部から呼ばれる用) -void -PowerDevice::MakePowerOn() -{ - gScheduler->SendMessage(MessageID::POWERON); -} - // リセットをスケジューラに指示する。(外部から呼ばれる用) void PowerDevice::MakeResetHard() @@ -60,13 +47,6 @@ PowerDevice::MakeResetHard() gScheduler->SendMessage(MessageID::RESET); } -// 電源オフ後終了をスケジューラに指示する。(外部から呼ばれる用) -void -PowerDevice::MakePowerOffExit() -{ - gScheduler->SendMessage(MessageID::POWEROFF_EXIT); -} - // リスタートをスケジューラに指示する。(外部から呼ばれる用) void PowerDevice::MakeRestart() @@ -74,11 +54,11 @@ PowerDevice::MakeRestart() gScheduler->SendMessage(MessageID::POWEROFF_RESTART); } -// 電源オンのメッセージコールバック +// 電源ボタンを押す。 (外部から呼ばれる用) void -PowerDevice::PowerOnCallback(MessageID msgid, uint32 arg) +PowerDevice::PowerButton() { - DoPowerOn(); + gScheduler->SendMessage(MessageID::POWER_BUTTON); } // リセットのメッセージコールバック @@ -95,6 +75,13 @@ PowerDevice::PowerOffCallback(MessageID DoPowerOff(msgid); } +// 電源ボタンのメッセージコールバック +void +PowerDevice::PowerButtonCallback(MessageID msgid, uint32 arg) +{ + DoPowerButton(); +} + // 電源オン操作 (Device::ResetHard ではない) void PowerDevice::DoPowerOn() @@ -168,3 +155,84 @@ PowerDevice::DoPowerOff(MessageID msgid) UIMessage::Post(UIMessage::APPEXIT); } } + +// 電源ボタン操作 +void +PowerDevice::DoPowerButton() +{ + putlog(1, "PowerButton"); + + if (gMainApp.GetVMType() == VMType::X68030) { + // X68030 の電源ボタンはオルタネート動作 + power_button = !power_button; + Change(); + // MFP の POWSW 信号は負論理 + gMFP->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.GetVMType() == VMType::X68030) { + DoPowerOff(MessageID::POWEROFF_EXIT); + } else { + gScheduler->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); + } +}