Annotation of nono/vm/power.cpp, revision 1.1.1.7

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.