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

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.5 ! root      204:        assertmsg(false, "PowerDevice::SetSystemPowerOn should not be called.");
1.1.1.4   root      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: }
                    227: 
                    228: // デストラクタ
                    229: LunaPowerDevice::~LunaPowerDevice()
                    230: {
                    231: }
1.1.1.2   root      232: 
1.1.1.5 ! root      233: // 初期化
        !           234: bool
        !           235: LunaPowerDevice::Init()
        !           236: {
        !           237:        if (inherited::Init() == false) {
        !           238:                return false;
        !           239:        }
        !           240: 
        !           241:        event.func = ToEventCallback(&LunaPowerDevice::PowerCallback);
        !           242:        event.time = 1_msec;
        !           243:        event.SetName("Power Off");
        !           244:        scheduler->RegistEvent(event);
        !           245: 
        !           246:        return true;
        !           247: }
        !           248: 
1.1.1.4   root      249: // PIO1 の PC4 が繋がっているということにする。
                    250: void
                    251: LunaPowerDevice::SetSystemPowerOn(bool poweron)
                    252: {
                    253:        if (poweron) {
                    254:                if (event.IsRunning()) {
                    255:                        putlog(1, "Cancel Power-Off");
                    256:                        scheduler->StopEvent(event);
                    257:                }
1.1.1.2   root      258:        } else {
1.1.1.4   root      259:                if (event.IsRunning() == false) {
                    260:                        putlog(1, "Start Power-Off timer");
                    261:                        scheduler->RestartEvent(event);
                    262:                }
1.1.1.2   root      263:        }
                    264: }
                    265: 
1.1.1.4   root      266: // LUNA の電源オフが信号状態の変化に対し 1msec 遅れて応答することを
                    267: // エミュレートするためのイベントコールバック。
                    268: void
                    269: LunaPowerDevice::PowerCallback(Event& ev)
                    270: {
                    271:        DoPowerOff(MessageID::POWEROFF_EXIT);
                    272: 
                    273:        // LED の状態が変わったことを UI に通知。
                    274:        led = ispower;
                    275:        UIMessage::Post(UIMessage::LED);
                    276: }
                    277: 
                    278: 
                    279: //
                    280: // 電源周り (X680x0)
                    281: //
                    282: 
                    283: // X68030 はフロントのオルタネートスイッチで電源オンにする。
                    284: // RTC 等でも電源オンは可能だが現状サポートしていないので省略。
                    285: //
                    286: // 電源オン後は以下のいずれか一つでも成り立っている間は電源オン。
                    287: //  1 電源ボタンがオン状態
                    288: //  2 ALARM_OUT がアサート
                    289: //  3 システムポートが電源オフコマンドを発行していない。
                    290: 
                    291: // コンストラクタ
                    292: X68030PowerDevice::X68030PowerDevice()
                    293:        : inherited()
                    294: {
                    295:        alternate_switch = true;
                    296: }
                    297: 
                    298: // デストラクタ
                    299: X68030PowerDevice::~X68030PowerDevice()
                    300: {
                    301: }
                    302: 
                    303: // 電源ボタン操作
                    304: void
                    305: X68030PowerDevice::DoPowerButton()
                    306: {
                    307:        putlog(1, "PowerButton");
                    308: 
                    309:        // X68030 の電源ボタンはオルタネート動作
                    310:        power_button = !power_button;
                    311:        Change();
                    312: 
                    313:        // MFP の POWSW 信号は負論理
                    314:        GetMFPDevice()->SetPowSW(!power_button);
                    315: }
                    316: 
1.1.1.2   root      317: // RP5C15 の ALARM_OUT を受け取る
                    318: void
1.1.1.4   root      319: X68030PowerDevice::SetAlarmOut(bool alarm_out_)
1.1.1.2   root      320: {
                    321:        alarm_out = alarm_out_;
                    322:        Change();
                    323: }
                    324: 
1.1.1.4   root      325: // システムポートからの電源オフコマンド発行で false が来る。
                    326: // 便宜上、電源投入時にはシステムポートがこれを true にする。
1.1.1.2   root      327: void
1.1.1.4   root      328: X68030PowerDevice::SetSystemPowerOn(bool poweron)
1.1.1.2   root      329: {
                    330:        system_poweron = poweron;
                    331:        Change();
                    332: }
                    333: 
                    334: // 電源状態の変更。
                    335: // power_button、alarm_out、system_poweron のいずれかの変更で呼ぶこと。
                    336: void
1.1.1.4   root      337: X68030PowerDevice::Change()
1.1.1.2   root      338: {
                    339:        bool old_power = ispower;
                    340:        bool new_power = power_button | alarm_out | system_poweron;
1.1.1.5 ! root      341:        putlog(1, "Change: old=%u new=%u (button=%u alarm=%u system=%u)",
1.1.1.4   root      342:                old_power, new_power, power_button, alarm_out, system_poweron);
1.1.1.2   root      343: 
                    344:        if (old_power == false && new_power) {
                    345:                DoPowerOn();
                    346:        } else if (old_power && new_power == false) {
1.1.1.4   root      347:                DoPowerOff(MessageID::POWEROFF_EXIT);
1.1.1.2   root      348:        }
                    349: 
                    350:        bool old_led = led;
1.1.1.4   root      351:        // 電源 LED は X68030 の電源制御部の回路による。
                    352:        led = power_button | alarm_out;
                    353: 
1.1.1.2   root      354:        if (old_led != led) {
                    355:                // LED の状態が変わったことを UI に通知
                    356:                UIMessage::Post(UIMessage::LED);
                    357:        }
                    358: }

unix.superglobalmegacorp.com

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