|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.11 root 7: //
8: // MFP (MC68901)
9: //
10:
1.1 root 11: #pragma once
12:
13: #include "device.h"
1.1.1.11 root 14: #include "event.h"
1.1.1.10 root 15: #include <array>
1.1 root 16:
1.1.1.13 root 17: class InterruptDevice;
1.1.1.18! root 18: class Syncer;
1.1.1.13 root 19: class X68030Keyboard;
20:
1.1 root 21: struct MFP
22: {
1.1.1.15 root 23: static const uint GPIP = 0; // $E88001
24: static const uint AER = 1; // $E88003
25: static const uint DDR = 2; // $E88005
26: static const uint IERA = 3; // $E88007
27: static const uint IERB = 4; // $E88009
28: static const uint IPRA = 5; // $E8800B
29: static const uint IPRB = 6; // $E8800D
30: static const uint ISRA = 7; // $E8800F
31: static const uint ISRB = 8; // $E88011
32: static const uint IMRA = 9; // $E88013
33: static const uint IMRB = 10; // $E88015
34: static const uint VR = 11; // $E88017
35: static const uint TACR = 12; // $E88019
36: static const uint TBCR = 13; // $E8801B
37: static const uint TCDCR = 14; // $E8801D
38: static const uint TADR = 15; // $E8801F
39: static const uint TBDR = 16; // $E88021
40: static const uint TCDR = 17; // $E88023
41: static const uint TDDR = 18; // $E88025
42: static const uint SCR = 19; // $E88027
43: static const uint UCR = 20; // $E88029
44: static const uint RSR = 21; // $E8802B
45: static const uint TSR = 22; // $E8802D
46: static const uint UDR = 23; // $E8802F
47: static const uint RegMax = 24;
1.1 root 48:
49: union ir16 {
50: uint16 w;
51: struct {
52: #if BYTE_ORDER == LITTLE_ENDIAN
53: uint8 b, a;
54: #else
55: uint8 a, b;
56: #endif
57: };
58: };
59:
60: // ハードウェア未実装ビットは書き込み時に '0' にする
61:
62: uint8 gpip;
63: uint8 aer;
64: uint8 ddr;
1.1.1.15 root 65: static const uint GPIP_HSYNC = 7;
66: static const uint GPIP_CIRQ = 6;
1.1 root 67: // 5 は常に '1'
1.1.1.15 root 68: static const uint GPIP_VDISP = 4;
69: static const uint GPIP_FMIRQ = 3;
70: static const uint GPIP_POWSW = 2;
71: static const uint GPIP_EXPON = 1;
72: static const uint GPIP_ALARM = 0;
1.1 root 73:
1.1.1.3 root 74: static const uint INTR_RTC_ALARM = 0;
75: static const uint INTR_EXPON = 1;
76: static const uint INTR_POW_SW = 2;
77: static const uint INTR_FM_IRQ = 3;
78: static const uint INTR_TIMER_D = 4;
79: static const uint INTR_TIMER_C = 5;
80: static const uint INTR_VDISP = 6;
81: static const uint INTR_unused = 7;
82: static const uint INTR_TIMER_B = 8;
83: static const uint INTR_TXERR = 9;
84: static const uint INTR_TXEMPTY = 10;
85: static const uint INTR_RXERR = 11;
86: static const uint INTR_RXFULL = 12;
87: static const uint INTR_TIMER_A = 13;
88: static const uint INTR_CRTC_IRQ = 14;
89: static const uint INTR_HSYNC = 15;
1.1 root 90: ir16 ier;
91: ir16 ipr;
92: ir16 isr;
93: ir16 imr;
1.1.1.6 root 94:
1.1.1.17 root 95: // b7 b6 b5 b4 b3 b2 b1 b0
96: // +-----+-----+-----+-----+-----+-----+-----+-----+
1.1.1.6 root 97: // VR | V7 | V6 | V5 | V4 | S | --- | --- | --- |
1.1.1.17 root 98: // +-----+-----+-----+-----+-----+-----+-----+-----+
99: // | | | | |
1.1.1.6 root 100: // | | | | +------------ In-Service Register Enable
101: // +-----+-----+-----+------------------ Vector Number
102: uint8 vr_vec; // ベクタの上位4ビット
103: uint8 vr_s; // %1:ソフトウェアEOI(ISR有効)、%0:自動EOI(ISR無効)
104: uint8 GetVR() const { return vr_vec | vr_s; }
1.1 root 105:
1.1.1.15 root 106: // タイマー
1.1.1.18! root 107: struct Timer {
! 108: // タイマー停止中は、カウンタの現在値 (1-256) を保持。
! 109: // タイマー動作中は、現在カウントダウン中のカウントの初期値(1-256)。
! 110: // TxDR レジスタ値際は、タイマー動作中/停止中どちらでも
! 111: // これではなく GetTDR() を使うこと。
1.1.1.15 root 112: uint32 tdr;
113:
1.1.1.18! root 114: // 次回の TxDR のリロード値 (1-256)。
1.1.1.15 root 115: uint32 next_tdr;
116:
1.1.1.18! root 117: // タイマーの開始時刻。
! 118: uint64 start;
! 119:
1.1.1.15 root 120: // tcr は書き込み値、現在のモードを保持する。
121: // TACR: --- --- --- RST AC3 AC2 AC1 AC0
122: // TBCR: --- --- --- RST BC3 BC2 BC1 BC0
123: // TCDCR: --- CC2 CC1 CC0 --- DC2 DC1 DC0
124: uint8 tcr;
1.1.1.18! root 125:
! 126: bool IsStopped() const noexcept { return (tcr == 0); }
! 127: bool IsDelay() const noexcept { return (0 < tcr && tcr < 8); }
! 128: bool IsEvent() const noexcept { return (tcr == 8); }
! 129: bool IsPulseWidth() const noexcept { return (tcr > 8); }
! 130:
! 131: // 現在時刻 now とメインカウンタ周期 period から
! 132: // 現在のメインカウンタの値を求める。
! 133: // タイマー動作中のみ呼ぶこと。
! 134: uint8 GetCounter(uint64 now, uint64 period) const;
1.1.1.15 root 135: } timer[4];
136:
137: // TCDCR の値
138: uint8 GetTCDCR() const {
139: return (timer[2].tcr << 4) | timer[3].tcr;
140: }
1.1 root 141:
142: uint8 scr;
1.1.1.3 root 143:
1.1.1.17 root 144: // b7 b6 b5 b4 b3 b2 b1 b0
145: // +-----+-----+-----+-----+-----+-----+-----+-----+
1.1.1.3 root 146: // UCR | CLK | WL | ST | PE | E/O | --- |
1.1.1.17 root 147: // +-----+-----+-----+-----+-----+-----+-----+-----+
148: // | | | | |
1.1.1.3 root 149: // | | | | +--------- %1で偶数パリティ
150: // | | | +--------------- %1でパリティエラー
151: // | | +------------------- スタート/ストップビット
152: // | +--- データ長 %00 同期
153: // | %00:8bit, %01:7bit %01 非同期 1bit/1bit
154: // | %10:6bit, %11:5bit %10 非同期 1bit/1.5bit
155: // | %11 非同期 1bit/2bit
156: // |
157: // +------------------------------------- %1 送受信速度が入力の1/16
158: static const uint32 UCR_CLK = 0x80;
159: static const uint32 UCR_WL = 0x60;
160: static const uint32 UCR_ST = 0x18;
161: static const uint32 UCR_PE = 0x04;
162: static const uint32 UCR_EO = 0x02;
163: uint8 ucr;
164:
1.1.1.17 root 165: // b7 b6 b5 b4 b3 b2 b1 b0
166: // +-----+-----+-----+-----+-----+-----+-----+-----+
1.1.1.3 root 167: // RSR | BF | OE | PE | FE | B | CIP | SS | RE |
1.1.1.17 root 168: // +-----+-----+-----+-----+-----+-----+-----+-----+
169: // | | | | | | | |
1.1.1.3 root 170: // | | | | | | | +--- %1 RX Enable
171: // | | | | | | +--------- Sync Stop
172: // | | | | | +--------------- 非同期なら
173: // | | | | | %1 Detect Start Bit
174: // | | | | | %0 Detect Stop Bit
175: // | | | | +--------------------- %1 非同期ならBreak
176: // | | | +--------------------------- %1 Framing Error
177: // | | +--------------------------------- %1 Parity Error
178: // | +--------------------------------------- %1 Overflow Error
179: // +--------------------------------------------- %1 RX Buffer Full
180: static const uint32 RSR_BF = 0x80;
181: static const uint32 RSR_OE = 0x40;
182: static const uint32 RSR_PE = 0x20;
183: static const uint32 RSR_FE = 0x10;
184: static const uint32 RSR_B = 0x08;
185: static const uint32 RSR_CIP = 0x04;
186: static const uint32 RSR_SS = 0x02;
187: static const uint32 RSR_RE = 0x01;
1.1 root 188: uint8 rsr;
1.1.1.3 root 189:
1.1.1.17 root 190: // b7 b6 b5 b4 b3 b2 b1 b0
191: // +-----+-----+-----+-----+-----+-----+-----+-----+
1.1.1.3 root 192: // TSR | BE | UE | AT | END | B | H | L | TE |
1.1.1.17 root 193: // +-----+-----+-----+-----+-----+-----+-----+-----+
194: // | | | |
1.1.1.3 root 195: // | | | +--- %1 TX Enable
196: // | | +--------------------------- %1 TX Disabled
197: // | +--------------------------------------- %1 Underrun Error
198: // +--------------------------------------------- %1 TX Buffer Empty
199: static const uint32 TSR_BE = 0x80;
200: static const uint32 TSR_UE = 0x40;
201: static const uint32 TSR_AT = 0x20;
202: static const uint32 TSR_END = 0x10;
203: static const uint32 TSR_B = 0x08;
204: static const uint32 TSR_H = 0x04;
205: static const uint32 TSR_L = 0x02;
206: static const uint32 TSR_TE = 0x01;
1.1 root 207: uint8 tsr;
208:
1.1.1.3 root 209: // 送受信レジスタ。
210: // 受信データがなければ -1 にする
211: uint16 udr;
1.1 root 212: };
213:
1.1.1.9 root 214: class MFPDevice : public IODevice
1.1 root 215: {
1.1.1.3 root 216: using inherited = IODevice;
1.1 root 217:
1.1.1.15 root 218: static const uint32 baseaddr = 0xe88000;
1.1 root 219:
220: public:
221: MFPDevice();
1.1.1.14 root 222: ~MFPDevice() override;
1.1 root 223:
1.1.1.13 root 224: bool Init() override;
1.1.1.11 root 225: void ResetHard(bool poweron) override;
1.1 root 226:
1.1.1.6 root 227: // 割り込みアクノリッジ
1.1.1.14 root 228: busdata InterruptAcknowledge();
1.1.1.6 root 229:
1.1.1.11 root 230: // HSync 入力
231: void SetHSync(bool hsync);
232:
1.1 root 233: // VDisp 入力
234: void SetVDisp(bool vdisp);
235:
1.1.1.12 root 236: // 電源ボタン状態入力
237: void SetPowSW(bool powsw);
238:
239: // ALARM 信号入力
240: void SetAlarmOut(bool alarm);
241:
1.1.1.3 root 242: // KEY CTRL 状態を設定する
243: void SetKeyCtrl(bool ctrl);
244:
1.1.1.8 root 245: // キーボードからの送信が可能なら true を返す。
246: bool RxIsReady() const;
1.1.1.3 root 247:
248: // キーボードからデータを受信
249: void Rx(uint32 data);
1.1.1.2 root 250:
1.1.1.3 root 251: protected:
252: // BusIO インタフェース
253: static const uint32 NPORT = 0x20;
1.1.1.15 root 254: busdata ReadPort(uint32 offset);
255: busdata WritePort(uint32 offset, uint32 data);
256: busdata PeekPort(uint32 offset);
257: bool PokePort(uint32 offset, uint32 data);
1.1.1.3 root 258:
259: private:
1.1.1.18! root 260: void SetIER(uint16 data);
1.1 root 261: void SetTCR(int ch, uint32 data);
1.1.1.2 root 262: uint8 GetTDR(int ch) const;
1.1 root 263: void SetTDR(int ch, uint32 data);
1.1.1.18! root 264: void RestartTimerEvent(int ch);
! 265: void StopTimerEvent(int ch);
! 266: bool IsTimerIntrEnable(int ch) const;
1.1 root 267:
268: // GPIP の信号状態をセットする
269: void SetGPIP(int num, bool val);
270:
1.1.1.3 root 271: void SetUCR(uint32 data);
272: void SetRSR(uint32 data);
273: void SetUDR(uint32 data);
274:
1.1.1.8 root 275: // RSR::BF ビットの状態を変える
276: void SetBF();
277: void ClearBF();
278: // MFP の RR 線の状態を返す
279: bool IsRR() const;
280:
1.1.1.3 root 281: // イベントコールバック
1.1.1.5 root 282: void TimerCallback(Event& ev);
283: void KeyCallback(Event& ev);
1.1 root 284:
1.1.1.6 root 285: // 必要なら割り込みを上げる
286: void SetInterrupt(uint ch);
287:
288: // 割り込み信号線の状態を変える
289: void ChangeInterrupt();
290:
1.1.1.9 root 291: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
292:
1.1 root 293: struct MFP mfp {};
1.1.1.10 root 294: std::array<Event, 4> event {};
1.1.1.9 root 295: Event key_event { this };
296:
1.1.1.18! root 297: // 各タイマーが刻んでいる時刻 (時間軸)
! 298: std::array<uint64, 4> stime {};
! 299:
! 300: // 各タイマーの周期
! 301: std::array<uint64, 4> rt_period {};
! 302:
! 303: // タイマーを実時間に追従する場合は true。
! 304: bool sync_rt {};
! 305:
1.1.1.16 root 306: Monitor *monitor {};
1.1.1.3 root 307:
1.1.1.13 root 308: InterruptDevice *interrupt {};
1.1.1.18! root 309: Syncer *syncer {};
1.1.1.13 root 310: X68030Keyboard *keyboard {};
311:
1.1 root 312: static const char *intrname[];
313: static const char *gpipname[];
1.1.1.18! root 314: static const uint64 prescale_ns[8];
1.1 root 315: static const char *prescale_str[8];
1.1.1.15 root 316: static const uint timer_vector[4];
317: static const char *regname[MFP::RegMax];
1.1 root 318: };
319:
1.1.1.13 root 320: static inline MFPDevice *GetMFPDevice() {
321: return Object::GetObject<MFPDevice>(OBJ_MFP);
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.