|
|
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:
7: #pragma once
8:
9: #include "device.h"
10:
11: // uPD7201/Z8530 のレジスタ
12: //
13: // uPD7201 は、書き込みが CR (Command Register) 8本、
14: // 読み込みが SR (Status Register) 2本。
15: // Z8530 は、書き込みが WR (Write Register) 16本、
16: // 読み込みが RR (Read Register) 8本。
17: //
18: // Z8530 の WR0..WR7、RR0..RR2 は (名前が異なるが)
19: // uPD7201 の CR0..CR7、SR0..SR2 とわりとよく似ている (所々違う)。
20: //
21: // そのためデバイスは uPD7201Device クラスを基底に、SIODevice
22: // (ほぼ uPD7201Device) と SCCDevice (Z8530) とに派生している。
23: // レジスタ構造体は C++ の制約的に両方のセットを持ったものを一つ
24: // 用意するほうが楽なので、こうなっている。
25: struct SIO
26: {
27: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
28: // CR0 | CRC | Command | Pointer |
29: static const int CR0_CRC = 0xc0;
30: static const int CR0_CMD = 0x38;
31: static const int CR0_PTR = 0x07;
32:
33: // Z8530 ではコマンド %000 と %001 がレジスタ切り替えなので、
34: // CMD が 0x38、PTR が 0x0f とあえて被せてある。
35: static const int WR0_CRC = CR0_CRC;
36: static const int WR0_CMD = CR0_CMD;
37: static const int WR0_PTR = 0x0f;
38:
39: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
40: // CR1 | WE | -- | WR | RX Int | -- | TE | ES |
41: // | | | | +---- E/S Int Enable
42: // | | | +--------- TX INT/DMA Enable
43: // | | +--------------------- RX Int Mode
44: // | +----------------------------- Wait on RX(=%1),TX(=%0)
45: // +--------------------------------------- Wait Enable
46: static const int CR1_WAIT_EN = 0x80;
47: static const int CR1_WAIT_RX = 0x20;
48: static const int CR1_RXINT = 0x18;
49: static const int CR1_TXINT_EN = 0x02;
50: static const int CR1_ESINT_EN = 0x01;
51:
52: static const int WR1_WAIT_EN = CR1_WAIT_EN;
53: static const int WR1_WAIT_RX = CR1_WAIT_RX;
54: static const int WR1_RXINT = CR1_RXINT;
55: static const int WR1_TXINT_EN = CR1_TXINT_EN;
56: static const int WR1_ESINT_EN = CR1_ESINT_EN;
57:
58: // CR1_RXINT
59: static const int RXINT_DISABLE = 0x00; // disabled
60: static const int RXINT_FIRSTCHAR = 0x08; // First charactoer intr.
61: static const int RXINT_ALL_INC_SPECIAL = 0x10; // All char include special
62: static const int RXINT_ALL_EXC_SPECIAL = 0x18; // All char exclude special
63:
64: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
65: // CR3 | RX bits | AE | -- -- -- -- | RE |
66: // | | +---- RX Enable
67: // | +----------------------------- Auto Enable
68: // +------------------------------------ RX bits
69: static const int CR3_RXBITS = 0xc0;
70: static const int CR3_AUTO_EN = 0x40;
71: static const int CR3_RX_EN = 0x01;
72:
73: static const int WR3_RXBITS = CR3_RXBITS;
74: static const int WR3_AUTO_EN = CR3_AUTO_EN;
75: static const int WR3_RX_EN = CR3_RX_EN;
76:
77: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
78: // CR4 | ClkRate | SyncMode| StopBits| PV | PE |
79: // | | | | +---- Parity Enable(%1)
80: // | | | +--------- Parity Even(%1)
81: // | | +---------------- Stop Bits
82: // | +-------------------------- Sync Mode
83: // +------------------------------------ Clock Rate
1.1.1.6 ! root 84: //
1.1 root 85: static const int CR4_CLKRATE = 0xc0;
86: static const int CR4_SYNCMODE = 0x30;
87: static const int CR4_STOPBITS = 0x0c;
88: static const int CR4_PARITY_EVEN= 0x02;
89: static const int CR4_PARITY_EN = 0x01;
90:
91: static const int WR4_CLKRATE = CR4_CLKRATE;
92: static const int WR4_SYNCMODE = CR4_SYNCMODE;
93: static const int WR4_STOPBITS = CR4_STOPBITS;
94: static const int WR4_PARITY_EVEN= CR4_PARITY_EVEN;
95: static const int WR4_PARITY_EN = CR4_PARITY_EN;
96:
97: static const int SYNC_8BIT = 0x00;
98: static const int SYNC_16BIT = 0x10;
99: static const int SYNC_HDLC = 0x20;
100: static const int SYNC_EXT = 0x30;
101:
102: static const int SYNC_MODE = 0x00;
103: static const int STOP_BITS_1 = 0x04;
104: static const int STOP_BITS_1_5 = 0x08;
105: static const int STOP_BITS_2 = 0x0c;
106:
107: enum Mode {
108: SYNC = 0,
109: ASYNC = 1,
110: HDLC = 2,
111: };
112:
113: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
114: // CR5 | DTR| TX bits | SB | TE | CRC| RTS| TC |
115: // | | | | | | +---- TX CRC Enable
116: // | | | | | +--------- ~RTS
117: // | | | | +-------------- CRC-16/CCITT
118: // | | | +------------------- TX Enable
119: // | | +------------------------ Send Break
120: // | +------------------------------- TX Bits
121: // +--------------------------------------- ~DTR
122: static const int CR5_DTR = 0x80;
123: static const int CR5_TXBITS = 0x60;
124: static const int CR5_SENDBREAK = 0x10;
125: static const int CR5_TX_EN = 0x08;
126: static const int CR5_CRC16 = 0x04;
127: static const int CR5_RTS = 0x02;
128: static const int CR5_TXCRC_EN = 0x01;
129:
130: static const int WR5_DTR = CR5_DTR;
131: static const int WR5_TXBITS = CR5_TXBITS;
132: static const int WR5_SENDBREAK = CR5_SENDBREAK;
133: static const int WR5_TX_EN = CR5_TX_EN;
134: static const int WR5_CRC16 = CR5_CRC16;
135: static const int WR5_RTS = CR5_RTS;
136: static const int WR5_TXCRC_EN = CR5_TXCRC_EN;
137:
138: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
139: // SR0 | BA | TU | CTS| SY | DCD| TE | IP | RA |
140: static const int SR0_BREAK = 0x80; // Break/Abort
141: static const int SR0_TXUNDER = 0x40; // Tx Underrun
142: static const int SR0_CTS = 0x20; // CTS
143: static const int SR0_SYNC = 0x10; // SYNC
144: static const int SR0_DCD = 0x08; // DCD
145: static const int SR0_TXEMPTY = 0x04; // Tx Buffer Empty
146: static const int SR0_INTPEND = 0x02; // Interrupt Pending
147: static const int SR0_RXAVAIL = 0x01; // Rx Character Available
148:
149: static const int RR0_BREAK = SR0_BREAK;
150: static const int RR0_TXUNDER = SR0_TXUNDER;
151: static const int RR0_CTS = SR0_CTS;
152: static const int RR0_SYNC = SR0_SYNC;
153: static const int RR0_DCD = SR0_DCD;
154: static const int RR0_TXEMPTY = SR0_TXEMPTY;
155: static const int RR0_INTPEND = SR0_INTPEND;
156: static const int RR0_RXAVAIL = SR0_RXAVAIL;
157:
158: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
159: // SR1 | EF | CRC| RO | PE | ResidueCode | AS |
160: static const int SR1_ENDOFFRAME = 0x80; // End of Frame
161: static const int SR1_CRCERROR = 0x40; // CRC/Framing Error
162: static const int SR1_RXOVERRUN = 0x20; // Rx Overrun
163: static const int SR1_PARITYERROR= 0x10; // Parity Error
164: static const int SR1_RESIDUEMASK= 0x0e; // Residue Code 2-0
165: static const int SR1_ALL_SENT = 0x01; // All Sent
166:
167: static const int RR1_ENDOFFRAME = SR1_ENDOFFRAME;
168: static const int RR1_CRCERROR = SR1_CRCERROR;
169: static const int RR1_RXOVERRUN = SR1_RXOVERRUN;
170: static const int RR1_PARITYERROR= SR1_PARITYERROR;
171: static const int RR1_RESIDUEMASK= SR1_RESIDUEMASK;
172: static const int RR1_ALL_SENT = SR1_ALL_SENT;
173:
1.1.1.5 root 174: // 割り込みベクタ ChB ChA
175: // Tx Buffer Empty %000 %100
176: // External/Status Change %001 %101
177: // Rx Character Available %010 %110
178: // Special Rx Condition %011 %111
179: // (この 3bit が V4-V2 か V2-V0 のところに出力される)
180: static const uint INTR_TX = (1U << 0);
181: static const uint INTR_ES = (1U << 1);
182: static const uint INTR_RX = (1U << 2);
183: static const uint INTR_SP = (1U << 3);
184:
185: // 割り込みあたりのロジック (uPD7201/7201A Figure 3-2 より INT 分のみ)
186: //
187: // Rx Disable (CR1:b1) *1 -----------------+ *1: Rx Enable (CR3:b0)
188: // | じゃなくて?
189: // +---+ |
190: // * RxCharAvailable ---->| | |
191: // | AND )--+ | +---+
192: // All/First RxChar --->| | | +---+ +->| |
193: // +---+ +->) | | AND )--+
194: // ) OR )-->| | |
195: // * Special Rx Condition ----------->) | +---+ | +-+
196: // +---+ +->) |
197: // ) | ---
198: // * External/Status -------------------------------------->) OR |o-> INT
199: // ) |
200: // +---+ +->) |
201: // * Tx Buffer Empty ---------------->| | +----+ | +-+
202: // | | | | |
203: // (Reset TxIntPend Cmd) --------->o| AND )-->| | |
204: // | | | | |
205: // Tx INT/DMA Enable (CR1:b1) ----->| | | AND )--+
206: // +---+ | |
207: // | |
208: // INT DMA Mode (CR2A b1-0) ----------------->| |
209: // +----+
210:
1.1 root 211: int cr2a; // CR2A
212: int vector;
213: struct channel {
214: // 二次変数など
215: int ptr; // CR0 で決まるレジスタ選択ポインタ
216: int id; // チャンネル番号。0 か 1
217: const char *name; // チャンネル名。"A" か "B"
218: const char *desc; // チャンネルの用途(モニタ表示用)
219: Mode mode; // CR4 で決まるモード
220:
221: // uPD7201 レジスタ
1.1.1.5 root 222: // CR0 の下位 3bit (PTR 部分) は読み出し時には使わないこと (代わりに
223: // ptr を使用する)。書き込み時は書き込んでよい(書き捨て)。
1.1 root 224: uint8 cr0;
225: uint8 cr1;
226: // CR2 は特殊なのでここにはない
227: uint8 cr3;
228: uint8 cr4;
229: uint8 cr5;
230: uint8 cr6; // CR6 (未実装)
231: uint8 cr7; // CR7 (未実装)
232:
233: uint8 sr0;
234: uint8 sr1;
235:
236: // ここから Z8530 拡張
1.1.1.5 root 237: uint8 wr10; // WR10
1.1 root 238: uint8 wr11; // WR11
239: uint16 tc; // WR12, WR13
240: uint8 wr14; // WR14
241: uint8 wr15; // WR15
242:
243: // ここからその他の内部状態
244: bool es_ratched; // E/S ビットがラッチされているか
245:
246: // 受信バッファは短いので先頭からの FIFO とし、
247: // 取り出したら前にずらす?
248: uint8 rxbuf[3]; // 受信バッファ(FIFO)
249: int rxlen; // 受信バッファの有効バイト数
1.1.1.5 root 250:
251: // First Char 用のフラグで、この受信で割り込みを起こすなら true。
252: // ALL なら常に true。FIRSTCHAR の時は最初が true で1文字目の受信
253: // 割り込みを出したところで false にする。
254: bool all_or_first;
255:
256: // Reset Tx Interrupt/DMA Pending コマンドによる Tx 割り込み抑制。
257: // 通常 true にしておき、コマンドが発行されたら false にする。
258: // XXX 解除するのはリセットでええんかな?
259: bool reset_txint_pend;
260:
261: uint int_asserted; // 割り込み要因を保持
1.1 root 262: } chan[2];
263: };
264:
265: class uPD7201Device
266: : public IODevice
267: {
1.1.1.3 root 268: using inherited = IODevice;
1.1 root 269: public:
270: uPD7201Device();
1.1.1.5 root 271: virtual ~uPD7201Device() override;
1.1 root 272:
1.1.1.6 ! root 273: void ResetHard() override;
1.1.1.4 root 274: void MonitorUpdate(TextScreen&) override;
1.1 root 275:
276: // 受信
277: bool Rx(int ch, uint32 data);
278:
279: protected:
280: // チップリセット
281: void Reset();
282:
283: void ResetChannel(struct SIO::channel *chan);
284: virtual uint8 ReadCtrl(struct SIO::channel *chan);
1.1.1.2 root 285: uint8 ReadData(struct SIO::channel *chan);
1.1 root 286: virtual void WriteCtrl(struct SIO::channel *chan, uint32 data);
287: void WriteData(struct SIO::channel *chan, uint32 data);
1.1.1.2 root 288: uint8 PeekCtrl(const struct SIO::channel *chan) const;
289: uint8 PeekData(const struct SIO::channel *chan) const;
1.1 root 290:
291: // 割り込みを上げる (上位デバイスで用意する)
292: virtual void Interrupt() = 0;
293:
294: struct SIO cr {};
295:
296: static const int bits_per_char[4];
297:
298: private:
1.1.1.5 root 299: void WriteCR0(struct SIO::channel *chan, uint32 data);
300: void WriteCR1(struct SIO::channel *chan, uint32 data);
301: void WriteCR2(struct SIO::channel *chan, uint32 data);
302: void WriteCR3(struct SIO::channel *chan, uint32 data);
303: void WriteCR4(struct SIO::channel *chan, uint32 data);
304: void WriteCR5(struct SIO::channel *chan, uint32 data);
305: void WriteCR6(struct SIO::channel *chan, uint32 data);
306: void WriteCR7(struct SIO::channel *chan, uint32 data);
307:
308: void ChangeInterrupt();
1.1.1.2 root 309:
1.1.1.4 root 310: void MonitorUpdateCh(TextScreen&, int ch, int xbase, int ybase);
311: void MonitorReg(TextScreen&,
312: int, int, uint32 reg, const char * const *names);
1.1 root 313: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.