--- nono/vm/mfp.cpp 2026/04/29 17:05:42 1.1.1.19 +++ nono/vm/mfp.cpp 2026/04/29 17:06:00 1.1.1.21 @@ -101,23 +101,25 @@ // 使っていないので、Timer-B は実質何もしていない。 #include "mfp.h" +#include "event.h" #include "interrupt.h" #include "keyboard.h" +#include "mainbus.h" #include "monitor.h" -#include "mpu.h" #include "scheduler.h" #include "syncer.h" #include "x68kkbd.h" // InsideOut p.135 -static const busdata wait = busdata::Wait(24 * 40_nsec); +/*static*/ const busdata +MFPDevice::wait = busdata::Wait(24 * 40_nsec); // コンストラクタ MFPDevice::MFPDevice() : inherited(OBJ_MFP) { monitor = gMonitorManager->Regist(ID_MONITOR_MFP, this); - monitor->func = ToMonitorCallback(&MFPDevice::MonitorUpdate); + monitor->SetCallback(&MFPDevice::MonitorScreen); monitor->SetSize(77, 26); } @@ -142,19 +144,18 @@ MFPDevice::Init() mfp.timer[ch].tdr = 256; } + auto evman = GetEventManager(); for (int ch = 0; ch < event.size(); ch++) { - event[ch].dev = this; - event[ch].func = ToEventCallback(&MFPDevice::TimerCallback); - event[ch].code = ch; - event[ch].SetName(string_format("MFP Timer-%c", ch + 'A')); - scheduler->RegistEvent(event[ch]); + event[ch] = evman->Regist(this, ch, + ToEventCallback(&MFPDevice::TimerCallback), + string_format("MFP Timer-%c", ch + 'A')); } // キーボード周りは x68kkbd.cpp のコメント参照 - key_event.func = ToEventCallback(&MFPDevice::KeyCallback); - key_event.time = 3750_usec; - key_event.SetName("MFP USART"); - scheduler->RegistEvent(key_event); + key_event = evman->Regist(this, + ToEventCallback(&MFPDevice::KeyCallback), + "MFP USART"); + key_event->time = 3750_usec; return true; } @@ -309,7 +310,8 @@ MFPDevice::ReadPort(uint32 offset) } else if (offset < MFP::RegMax) { putlogn("%s -> $%02x", regname[offset], data.Data()); } else { - putlogn("$%06x -> $%02x", mpu->GetPaddr(), data.Data()); + putlogn("$%06x -> $%02x", + GetMainbusDevice()->GetPaddr(), data.Data()); } } data |= wait; @@ -535,7 +537,7 @@ MFPDevice::PokePort(uint32 offset, uint3 } void -MFPDevice::MonitorUpdate(Monitor *, TextScreen& screen) +MFPDevice::MonitorScreen(Monitor *, TextScreen& screen) { MFP mfp_; std::array tdr_; @@ -606,7 +608,7 @@ MFPDevice::MonitorUpdate(Monitor *, Text screen.Print(0, y++, " %-6s %-4s %-4s %-4s", "IER", "IMR", "IPR", "ISR"); for (int i = 15; i >= 0; i--, y++) { - uint16 mask = (1 << i); + uint16 mask = (1U << i); screen.Print(0, y, "%c%u:%-12s %-6s %-4s %-4s %-4s", i >= 8 ? 'A' : 'B', (i % 8), @@ -644,7 +646,7 @@ MFPDevice::MonitorUpdate(Monitor *, Text y = 9 + 8; screen.Puts(x, y++, " GPIP AER DDR"); for (int i = 7; i >= 0; i--, y++) { - uint mask = (1 << i); + uint mask = (1U << i); screen.Print(x, y, "b%u %-6s %u %u %s", i, gpipname[i], (mfp_.gpip & mask) ? 1 : 0, (mfp_.aer & mask) ? 1 : 0, @@ -686,7 +688,7 @@ MFPDevice::gpipname[] = { // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す /*static*/ const uint64 -MFPDevice::prescale_ns[8] = { +MFPDevice::prescale_tsec[8] = { 0, 1000_nsec, // /4 2500_nsec, // /10 @@ -734,7 +736,7 @@ MFPDevice::SetIER(uint16 new_ier) for (int ch = 0; ch < countof(mfp.timer); ch++) { uint timer_mask = 1U << timer_vector[ch]; if ((raising & timer_mask) != 0 && mfp.timer[ch].IsDelay()) { - event[ch].SetName(string_format("MFP Timer-%c", ch + 'A')); + event[ch]->SetName(string_format("MFP Timer-%c", ch + 'A')); RestartTimerEvent(ch); } } @@ -777,7 +779,7 @@ MFPDevice::SetTCR(int ch, uint32 data) // ここで TDR を確定させる。 // タイマー動作中の TDR の参照はイベント開始時刻から求めていたが // イベントを停止すると求められなくなるので、停止前に求めておく。 - uint64 period = prescale_ns[prev]; + uint64 period = prescale_tsec[prev]; uint64 now = scheduler->GetVirtTime(); mfp.timer[ch].tdr = timer.GetCounter(now, period); @@ -797,17 +799,17 @@ MFPDevice::SetTCR(int ch, uint32 data) // タイマー開始時は TDR はリロードしない。 // 割り込みを上げる必要がある時だけイベントを使う。 - uint64 period = prescale_ns[data]; + uint64 period = prescale_tsec[data]; uint64 now = scheduler->GetVirtTime(); timer.start = now; if (IsTimerIntrEnable(ch)) { - event[ch].time = period * timer.tdr; - event[ch].SetName(string_format("MFP Timer-%c", ch + 'A')); + event[ch]->time = period * timer.tdr; + event[ch]->SetName(string_format("MFP Timer-%c", ch + 'A')); if (sync_rt) { // 自分の実時間軸の基準をここにする。 stime[ch] = syncer->GetRealTime(); // event.time はこの後変動するので、周期は別で覚えておく。 - rt_period[ch] = event[ch].time; + rt_period[ch] = event[ch]->time; scheduler->StartRealtimeEvent(event[ch], stime[ch], rt_period[ch]); @@ -815,14 +817,13 @@ MFPDevice::SetTCR(int ch, uint32 data) scheduler->RestartEvent(event[ch]); } } else { - event[ch].SetName(string_format("MFP Timer-%c FreeRun", ch + 'A')); + event[ch]->SetName(string_format("MFP Timer-%c FreeRun", ch + 'A')); } - putlog(1, "Timer-%c Start Delay mode(%u x %u.%uusec)", + putlog(1, "Timer-%c Start Delay mode(%u x %.1fusec)", ch + 'A', timer.tdr, - (uint)period / 1000, - (uint)(period / 100) % 10); + (double)period / 1_usec); return; } else if (data == 8) { @@ -857,7 +858,7 @@ MFPDevice::GetTDR(int ch) const // ディレイモード動作中なら現在値は保持していないので、算出する。 // XXX sync_rt == true で割り込み有効にしているタイマーの // TDR を読み出しても割り込みと整合しないがもう仕方ない。 - uint64 period = prescale_ns[timer.tcr]; + uint64 period = prescale_tsec[timer.tcr]; uint64 now = scheduler->GetVirtTime(); return timer.GetCounter(now, period); @@ -903,9 +904,9 @@ MFPDevice::SetTDR(int ch, uint32 data) // イベントコールバック void -MFPDevice::TimerCallback(Event& ev) +MFPDevice::TimerCallback(Event *ev) { - int ch = ev.code; + int ch = ev->code; MFP::Timer& timer = mfp.timer[ch]; // TDR がゼロになったところで呼ばれるので、TDR をリロードする @@ -913,10 +914,10 @@ MFPDevice::TimerCallback(Event& ev) timer.tdr = timer.next_tdr; timer.start = 0; // TDR (のリロード値) が変わったのでタイマー周りも再設定。 - uint64 period = prescale_ns[timer.tcr]; - ev.time = period * timer.tdr; + uint64 period = prescale_tsec[timer.tcr]; + ev->time = period * timer.tdr; if (sync_rt) { - rt_period[ch] = ev.time; + rt_period[ch] = ev->time; } } @@ -944,7 +945,7 @@ MFPDevice::TimerCallback(Event& ev) } } else { // タイマー動作中に IER を下げた時にはここで次回以降のイベントを停止。 - ev.SetName(string_format("MFP Timer-%c FreeRun", ch + 'A')); + ev->SetName(string_format("MFP Timer-%c FreeRun", ch + 'A')); } } @@ -957,9 +958,9 @@ MFPDevice::RestartTimerEvent(int ch) assert(timer.start != 0); uint64 now = scheduler->GetVirtTime(); - uint64 period = prescale_ns[timer.tcr]; + uint64 period = prescale_tsec[timer.tcr]; uint64 timeout = period * timer.tdr; - event[ch].time = timeout - ((now - timer.start) % timeout); + event[ch]->time = timeout - ((now - timer.start) % timeout); scheduler->RestartEvent(event[ch]); } @@ -968,7 +969,7 @@ void MFPDevice::StopTimerEvent(int ch) { scheduler->StopEvent(event[ch]); - event[ch].SetName(string_format("MFP Timer-%c Stopped", ch + 'A')); + event[ch]->SetName(string_format("MFP Timer-%c Stopped", ch + 'A')); mfp.timer[ch].start = 0; } @@ -997,7 +998,7 @@ MFPDevice::SetVDisp(bool vdisp) // TAI への入力はイベントカウントモードの時のみ if (timer.IsEvent()) { // AER が示す方向と同じエッジ方向の時 - bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP)); + bool aer = (mfp.aer & (1U << MFP::GPIP_VDISP)); if (aer == vdisp) { // カウンタを減算 timer.tdr--; @@ -1033,8 +1034,8 @@ MFPDevice::SetAlarmOut(bool alarm) void MFPDevice::SetGPIP(int num, bool val) { - bool aer = (mfp.aer & (1 << num)); - bool old = (mfp.gpip & (1 << num)); + bool aer = (mfp.aer & (1U << num)); + bool old = (mfp.gpip & (1U << num)); // 立ち上がりか立ち下がりで割り込みを上げる (AER による) // AER OLD VAL Interrupt @@ -1061,9 +1062,9 @@ MFPDevice::SetGPIP(int num, bool val) } if (val) { - mfp.gpip |= (1 << num); + mfp.gpip |= (1U << num); } else { - mfp.gpip &= ~(1 << num); + mfp.gpip &= ~(1U << num); } } @@ -1168,7 +1169,7 @@ MFPDevice::RxIsReady() const // だが、そもそもキーボードは送出作業中で、新たな送信はできないはずなので // この場合、つまり key_event の動作中も false (送信不可) にする。 - return !IsRR() && !key_event.IsRunning(); + return !IsRR() && !key_event->IsRunning(); } // キーボードからデータを受信 @@ -1178,16 +1179,16 @@ MFPDevice::Rx(uint32 data) // ここは受信したビットをシフトレジスタへ入れ始めたところに相当する // ので、まだ Buffer Full は立てない。 - key_event.code = data; + key_event->code = data; scheduler->RestartEvent(key_event); } // キーボードからのデータが受信し終わった頃に呼ばれるイベント。 void -MFPDevice::KeyCallback(Event& ev) +MFPDevice::KeyCallback(Event *ev) { // UDR にデータを置いて Buffer Full をセット - mfp.udr = ev.code; + mfp.udr = ev->code; SetBF(); // Manual 7-5 7.2.1 Receiver Interrupt Channels より