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