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

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

unix.superglobalmegacorp.com

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