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

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

unix.superglobalmegacorp.com

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