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