|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // uPD7201(MPSC) と Z8530(SCC) の共通部分 (シリアルポート1個つき)
9: //
10:
11: #pragma once
12:
13: #include "device.h"
14: #include "event.h"
15: #include "message.h"
16: #include <array>
17:
18: #if defined(MPSCC_SIO_LOG_HACK)
19: // SIO で SR0 のログ表示に細工をするため、
20: // SIO, MPSCC で putlog() マクロを再定義している。
21: #undef putlog
22: #define putlog(lv, fmt...) do { \
23: if (__predict_false(loglevel >= (lv))) { \
24: putlogn(fmt); \
25: sr0_logphase = 0; \
26: } \
27: } while (0)
28: #endif
29:
30: class HostCOMDevice;
1.1.1.3 root 31: class InterruptDevice;
1.1 root 32:
33: // 1チャンネル分の共通部分
34: class MPSCCChan
35: {
36: public:
37: MPSCCChan();
38: virtual ~MPSCCChan();
39:
40: void Init(int id_);
41:
42: // プロパティっぽいもの
43: int id {}; // チャンネル番号 (0 or 1)
44: char name {}; // チャンネル名 ('A' or 'B')
45: const char *desc {}; // チャンネルの用途(モニタ表示用)
46: uint32 ctrladdr {}; // 制御ポートのアドレス (モニタ表示用)
47: uint32 dataaddr {}; // データポートのアドレス (モニタ表示用)
48:
49: // ここから内部構造
50:
51: // CR0/WR0 付近
52: uint8 crc_cmd {}; // CRC
53: uint8 cmd {}; // Command
54: uint ptr {}; // Pointer (uPD7201 は 3bit、Z8530 は実質 4bit)
55:
56: // CR1/WR1 付近
57: bool wait_enable {}; // b7
58: bool wait_func {}; // b6; Z8530 Only
59: bool wait_on_rx {}; // b5
60: bool txint_enable {}; // b1
61: bool esint_enable {}; // b0
62:
63: // Z8530 では割り込みモード3種類とパリティエラーを Sp.Rx に含むかどうかが
64: // 独立して選択できるため、組み合わせは 3 * 2 (+ Disable 1通り) = 7通り。
65: // uPD7201 ではこれに相当する設定は RXINT の 2bit しかなく、Disable を除く
66: // 3通りはこのうち 3つがプリセットされたような感じ。
67: // (もちろん歴史的経緯はこの逆だろうけど)
68: //
69: // RXInt SP 割込モード Parity Error を Sp.Rx に含むか
70: // ----------------- ------------ ------------------------------
71: // 0 0 - : Disable -
72: // uPD7201 0 1 - : 1stChar no
73: // uPD7201 1 0 - : AllChar yes
74: // uPD7201 1 1 - : AllChar no
75: // Z8530 0 1 0 : 1stChar no
76: // Z8530 0 1 1 : 1stChar yes
77: // Z8530 1 0 0 : AllChar no
78: // Z8530 1 0 1 : AllChar yes
79: // Z8530 1 1 0 : SpOnly no
80: // Z8530 1 1 1 : SpOnly yes
81: static const uint RXINT_DISABLE = 0x00;
82: static const uint RXINT_1STCHAR = 0x01;
83: static const uint RXINT_ALLCHAR = 0x02;
84: static const uint RXINT_SPONLY = 0x03; // Z8530 Only
85: uint rxint_mode {};
86: bool sp_parity {};
87:
88: // SR0/RR0 付近
89: bool break_detected {};
90: bool tx_underrun {};
91: bool nCTS {};
92: bool nSYNC {};
93: bool nDCD {};
94:
95: // これらのレジスタは uPD7201/Z8530 で共通
96:
1.1.1.2 root 97: // CR3/WR3 付近
1.1.1.5 root 98: uint rxbits {}; // 受信データビット数 (レジスタ値ではない)
1.1.1.2 root 99: uint8 cr3_sync {}; // SyncMode でだけ使う bit4-1 を保存
100: bool auto_enable {};
1.1 root 101: bool rx_enable {};
1.1.1.2 root 102:
103: // CR4/WR4 付近
1.1.1.5 root 104: uint clkrate {}; // クロック倍率 (レジスタ値ではない)
1.1.1.2 root 105: uint8 syncmode {}; // bit5,4 を保存
106: uint8 stopbits {}; // STOPBITS_*
107: bool parity_even {};
108: int parity_enable {}; // パリティ有効 (追加するビット数 0 か 1 で保持)
109:
110: // CR5/WR5 付近
111: bool nDTR {}; // ~DTR
1.1.1.5 root 112: uint txbits {}; // 送信データビット数 (レジスタ値ではない)
1.1.1.2 root 113: bool sendbreak {};
1.1 root 114: bool tx_enable {};
1.1.1.2 root 115: bool crc16 {};
116: bool nRTS {}; // ~RTS
117: bool txcrc_en {};
118:
1.1 root 119: uint8 cr6 {};
120: uint8 cr7 {};
121: uint8 sr1 {};
122:
1.1.1.2 root 123: // いずれもレジスタイメージとして保存
124: uint8 old_cr3 {};
125: uint8 old_cr4 {};
126: uint8 old_cr5 {};
127:
1.1 root 128: // Z8530 専用のレジスタだけど継承とかは面倒なので結局ここに置く
129: uint8 wr10 {};
130: uint8 wr11 {};
131: uint16 tc {}; // WR12, WR13
132: uint8 wr14 {};
133: uint8 wr15 {};
134: uint8 rr10 {};
135:
136: // ここからその他の内部状態
137:
138: bool es_latched {}; // E/S ビットがラッチされているか
139:
140: // 受信バッファは短いので先頭からの FIFO とし、
141: // 取り出したら前にずらす
142: uint8 rxbuf[3] {}; // 受信バッファ(FIFO)
143: int rxlen {}; // 受信バッファの有効バイト数
144:
145: uint8 txbuf {}; // 送信バッファ
146: int txlen {}; // 送信バッファの有効バイト数
147: uint8 tx_shiftreg {}; // 送信シフトレジスタ相当品
148:
149: // First Char 用のフラグで、この受信で割り込みを起こすなら true。
150: // ALL なら常に true。FIRSTCHAR の時は最初が true で1文字目の受信
151: // 割り込みを出したところで false にする。
152: bool all_or_first {};
153:
154: // Tx 割り込み発火用のフラグ。
155: // Tx 割り込みは
156: // 1) Tx 割り込みが有効で
157: // 2) 送信バッファに書き込まれるか Reset Tx INT/DMA Pending コマンドが
158: // 発行されるかした後
159: // 3) 送信バッファが空になった
160: // 場合に発生する。チャンネルリセットとハードリセットで送信バッファが
161: // 空になった場合には発生しない。
162: // ので、ここの 2) を満たす場合 txint_ready = true とする。
163: bool txint_ready {};
164:
165: // 割り込みペンディング (MPSCC::INTPEND_*)
166: //
167: // Z8530 の RR3A レジスタは個別の割り込みペンディング状態が読み出せる。
168: // uPD7201 にも内部に同じだけの状態を持っているが個別に読み出す方法はなく
169: // すべてを OR したペンディングの有無を SR0A b1 で読み出すことが出来る。
170: uint intpend {};
171:
172: // ボーレート (表示用)
173: // Z8530 なら tc から求められる
174: double baudrate {};
175:
176: // 1フレームあたりの送受信のビット数 (表示用)
1.1.1.5 root 177: uint txframebits {};
178: uint rxframebits {};
1.1.1.2 root 179:
180: // LUNA の場合は TxC, RxC ピンに供給されているクロック。
181: // X68030 の場合は Z8530 内部で生成されている基準クロック。
182: // 誤差を減らすため 12 ビット分の時間 [nsec] としている。
183: uint64 xc12_ns {};
184:
185: // 実際の 12 ビットの通信にかかる時間。xc12_ns に倍率をかけたもの。
186: uint64 bit12_ns {};
1.1 root 187: };
188:
189: class MPSCC
190: {
191: public:
192: // レジスタ定義
193:
194: // b7 b6 b5 b4 b3 b2 b1 b0
195: // +---------+--------------+--------------+
196: // CR0 | CRC | Command | Pointer |
197: // WR0 +---------+--------------+--------------+
198: //
199: static const uint8 CR0_CRC = 0xc0;
200: static const uint8 CR0_CMD = 0x38;
201: static const uint8 CR0_PTR = 0x07;
202: // Z8530 ではコマンド %000 と %001 がレジスタ切り替えなので、
203: // CMD が 0x38、PTR が 0x0f とあえて被せてある。
204: static const uint8 WR0_CRC = CR0_CRC;
205: static const uint8 WR0_CMD = CR0_CMD;
206: static const uint8 WR0_PTR = 0x0f;
207:
208: // b7 b6 b5 b4 b3 b2 b1 b0
209: // +----+----+----+---------+----+----+----+
210: // CR1 | WE | 0 | WR | RX Int | SAV| TE | ES |
211: // +----+----+----+---------+----+----+----+
212: // | | | | | +---- E/S Int Enable
213: // | | | | +--------- TX INT/DMA Enable
214: // | | | +-------------- Status Affects Vec.(Ch.B)
215: // | | +--------------------- RX Int Mode
216: // | +----------------------------- Wait on RX(=%1),TX(=%0)
217: // +--------------------------------------- Wait Enable
218: //
219: static const uint8 CR1_WAIT_EN = 0x80; // Wait Enable
220: static const uint8 CR1_WAIT_RX = 0x20; // Wait on RX
221: static const uint8 CR1_RXINT = 0x18; // Rx Interrupt Mode
222: static const uint8 CR1_RXINT_DISABLE = 0x00; // Disable
223: static const uint8 CR1_RXINT_1STCHAR = 0x08; // 1st Char
224: static const uint8 CR1_RXINT_ALLCHAR = 0x10; // All Chars
225: static const uint8 CR1_RXINT_ALL_BUT_PE = 0x18; // All Chars exclude P.E.
226: static const uint8 CR1_SAV = 0x04; // Status Affects Vector (Ch.B)
227: static const uint8 CR1_TXINT_EN = 0x02; // Tx Int/DMA Enable
228: static const uint8 CR1_ESINT_EN = 0x01; // E/S Interrupt Enable
229: //
230: // b7 b6 b5 b4 b3 b2 b1 b0
231: // +----+----+----+---------+----+----+----+
232: // WR1 | WE | WF | WR | RX Int | SP | TE | ES |
233: // +----+----+----+---------+----+----+----+
234: // | +-------------- Sp includes Parity Err
235: // +---------------------------------- Wait Function
236: //
237: static const uint8 WR1_WAIT_EN = CR1_WAIT_EN;
238: static const uint8 WR1_WAIT_FUNC = 0x40; // Wait Function
239: static const uint8 WR1_WAIT_RX = CR1_WAIT_RX;
240: static const uint8 WR1_RXINT = CR1_RXINT;
241: static const uint8 WR1_RXINT_DISABLE = 0x00; // Disable
242: static const uint8 WR1_RXINT_1STCHAR = 0x08; // 1st Char or Sp.Cond.
243: static const uint8 WR1_RXINT_ALLCHAR = 0x10; // All Chars or Sp.Cond.
244: static const uint8 WR1_RXINT_SPONLY = 0x18; // Special Conditoin Only
245: static const uint8 WR1_SP_INC_PE = 0x04; // Sp. Condition includes P.E.
246: static const uint8 WR1_TXINT_EN = CR1_TXINT_EN;
247: static const uint8 WR1_ESINT_EN = CR1_ESINT_EN;
248:
249: // b7 b6 b5 b4 b3 b2 b1 b0
250: // +----+----+----+---------+----+---------+
251: // CR2A | R/S| 0 | VM | IntMode | PS | Int/DMA |
252: // +----+----+----+---------+----+---------+
253: // | | | | +------ INT/DMA Mode
254: // | | | +-------------- Priority Select
255: // | | +--------------------- Interrupt Mode -> VIS
256: // | +----------------------------- Vector Mode
257: // +--------------------------------------- ~RTSB/~SYNCB Select
258: //
259: static const uint8 CR2_SYNCB = 0x80; // ~RTSB/~SYNCB Select
260: static const uint8 CR2_VM = 0x20; // Vector Mode
261: static const uint8 CR2_INT = 0x18; // Interrupt Mode -> VIS
262: static const uint8 CR2_PRIOSEL = 0x04; // Priority Select
263: static const uint8 CR2_INTDMA = 0x03; // Int/DMA Mode
264:
265: // b7 b6 b5 b4 b3 b2 b1 b0
266: // +---------+----+-------------------+----+
267: // CR3 | RX bits | AE | (For sync mode) | RE |
268: // WR3 +---------+----+-------------------+----+
269: // | | +---- RX Enable
270: // | +----------------------------- Auto Enable
271: // +------------------------------------ RX bits
272: //
273: static const uint8 CR3_RXBITS = 0xc0; // Rx Bits
274: static const uint8 CR3_AUTO_EN = 0x40; // Auto Enable
1.1.1.2 root 275: static const uint8 CR3_SYNC_MASK = 0x1e;
1.1 root 276: static const uint8 CR3_RX_EN = 0x01; // Rx Enable
277: // WR3
278: static const uint8 WR3_RXBITS = CR3_RXBITS;
279: static const uint8 WR3_AUTO_EN = CR3_AUTO_EN;
280: static const uint8 WR3_RX_EN = CR3_RX_EN;
281:
282: // 並び順が 5, 6, 7, 8 でないので注意
283: static const uint8 RXBITS_5 = 0x00;
284: static const uint8 RXBITS_7 = 0x40;
285: static const uint8 RXBITS_6 = 0x80;
286: static const uint8 RXBITS_8 = 0xc0;
287:
288: // b7 b6 b5 b4 b3 b2 b1 b0
289: // +---------+---------+---------+----+----+
290: // CR4 | ClkRate | SyncMode| StopBits| PEV| PEN|
291: // WR4 +---------+---------+---------+----+----+
292: // | | | | +---- Parity Enable(%1)
293: // | | | +--------- Parity Even(%1)
294: // | | +---------------- Stop Bits
295: // | +-------------------------- Sync Mode
296: // +------------------------------------ Clock Rate
297: //
298: static const uint8 CR4_CLKRATE = 0xc0; // Clock Rate
299: static const uint8 CR4_SYNCMODE = 0x30; // Sync Mode
300: static const uint8 CR4_STOPBITS = 0x0c; // Stop Bits
301: static const uint8 CR4_PARITY_EVEN = 0x02; // Parity Even
302: static const uint8 CR4_PARITY_EN = 0x01; // Parity Enable
303: // WR4
304: static const uint8 WR4_CLKRATE = CR4_CLKRATE;
305: static const uint8 WR4_SYNCMODE = CR4_SYNCMODE;
306: static const uint8 WR4_STOPBITS = CR4_STOPBITS;
307: static const uint8 WR4_PARITY_EVEN = CR4_PARITY_EVEN;
308: static const uint8 WR4_PARITY_EN = CR4_PARITY_EN;
309:
1.1.1.2 root 310: static const uint8 CLKRATE_1 = 0x00;
311: static const uint8 CLKRATE_16 = 0x40;
312: static const uint8 CLKRATE_32 = 0x80;
313: static const uint8 CLKRATE_64 = 0xc0;
314:
315: static const uint8 STOPBITS_SYNC = (0x00 >> 2);
316: static const uint8 STOPBITS_1 = (0x04 >> 2);
317: static const uint8 STOPBITS_1_5 = (0x08 >> 2);
318: static const uint8 STOPBITS_2 = (0x0c >> 2);
1.1 root 319:
320: // b7 b6 b5 b4 b3 b2 b1 b0
321: // +----+---------+----+----+----+----+----+
322: // CR5 |~DTR| TX bits | SB | TE | CRC|~RTS| TCE|
323: // WR5 +----+---------+----+----+----+----+----+
324: // | | | | +---- TX CRC Enable
325: // | | | +-------------- CRC-16/CCITT
326: // | | +------------------- TX Enable
327: // | +------------------------ Send Break
328: // +------------------------------- TX Bits
329: static const uint8 CR5_nDTR = 0x80; // ~DTR
330: static const uint8 CR5_TXBITS = 0x60; // Tx Bits
331: static const uint8 CR5_SENDBREAK = 0x10; // Send Break
332: static const uint8 CR5_TX_EN = 0x08; // Tx Enable
333: static const uint8 CR5_CRC16 = 0x04; // CRC-16/CCITT
334: static const uint8 CR5_nRTS = 0x02; // ~RTS
335: static const uint8 CR5_TXCRC_EN = 0x01; // Tx CRC Enable
336: // WR5
337: static const uint8 WR5_nDTR = CR5_nDTR;
338: static const uint8 WR5_TXBITS = CR5_TXBITS;
339: static const uint8 WR5_SENDBREAK = CR5_SENDBREAK;
340: static const uint8 WR5_TX_EN = CR5_TX_EN;
341: static const uint8 WR5_CRC16 = CR5_CRC16;
342: static const uint8 WR5_nRTS = CR5_nRTS;
343: static const uint8 WR5_TXCRC_EN = CR5_TXCRC_EN;
344:
345: // 並び順が 5, 6, 7, 8 でないので注意
346: static const uint8 TXBITS_5 = 0x00;
347: static const uint8 TXBITS_7 = 0x20;
348: static const uint8 TXBITS_6 = 0x40;
349: static const uint8 TXBITS_8 = 0x60;
350:
351: // b7 b6 b5 b4 b3 b2 b1 b0
352: // +---------+----+----+----+----+----+----+
353: // WR9A | Reset | 0 |SHSL| MIE| DLC| NV | VIS|
354: // WR9B +---------+----+----+----+----+----+----+
355: // | | | | | +---- Vector Includes Status
356: // | | | | +--------- No Vector Mode
357: // | | | +-------------- Disable Lower Chain
358: // | | +------------------- Master Interrupt Enable
359: // | +------------------------ StatusHigh / StatusLow
360: // +------------------------------------ Reset Command
361: // Reset Command は CR0 のコマンドも参照のこと。
362: //
363: static const uint8 WR9_RESET_CMD = 0xc0; // Reset Command
364: static const uint8 WR9_SHSL = 0x10; // Status High / Status Low
365: static const uint8 WR9_MIE = 0x08; // Master Interrupt Enable
366: static const uint8 WR9_DLC = 0x04; // Disable Lower Chain
367: static const uint8 WR9_NV = 0x02; // No Vector Mode
368: static const uint8 WR9_VIS = 0x01; // Vector Includes Status
369:
370: // b7 b6 b5 b4 b3 b2 b1 b0
371: // +----+----+----+----+----+----+----+----+
372: // SR0 | B/A| T/E|~CTS|~S/H|~DCD| TE | IP | RA |
373: // +----+----+----+----+----+----+----+----+
374: // | | | | | +---- Rx Char. Available
375: // | | | | +--------- Interrupt Pending
376: // | | | +-------------- Tx Buffer Empty
377: // | | +------------------------ ~SYNC/Hunt
378: // | +---------------------------------- Tx Underrun/EOM
379: // +--------------------------------------- Break/Abort
380: //
381: static const uint8 SR0_BREAK = 0x80; // Break/Abort
382: static const uint8 SR0_TXUNDER = 0x40; // Tx Underrun/EOM
383: static const uint8 SR0_nCTS = 0x20; // ~CTS
384: static const uint8 SR0_nSYNC = 0x10; // ~SYNC/Hunt
385: static const uint8 SR0_nDCD = 0x08; // ~DCD
386: static const uint8 SR0_TXEMPTY = 0x04; // Tx Buffer Empty
387: static const uint8 SR0_INTPEND = 0x02; // Interrupt Pending
388: static const uint8 SR0_RXAVAIL = 0x01; // Rx Character Available
389: //
390: // +----+----+----+----+----+----+----+----+
391: // RR0 | B/A| T/E|~CTS|~S/H|~DCD| TE | ZC | RA |
392: // +----+----+----+----+----+----+----+----+
393: // +--------- Zero Count
394: //
395: static const uint8 RR0_BREAK = SR0_BREAK;
396: static const uint8 RR0_TXUNDER = SR0_TXUNDER;
397: static const uint8 RR0_nCTS = SR0_nCTS;
398: static const uint8 RR0_nSYNC = SR0_nSYNC;
399: static const uint8 RR0_nDCD = SR0_nDCD;
400: static const uint8 RR0_TXEMPTY = SR0_TXEMPTY;
401: static const uint8 RR0_ZEROCNT = 0x02; // Zero Count
402: static const uint8 RR0_RXAVAIL = SR0_RXAVAIL;
403:
404: // b7 b6 b5 b4 b3 b2 b1 b0
405: // +----+----+----+----+--------------+----+
406: // SR1 | EF | FRE| RO | PE | ResidueCode | AS |
407: // RR1 +----+----+----+----+--------------+----+
408: //
409: static const uint8 SR1_ENDOFFRAME = 0x80; // End of Frame
410: static const uint8 SR1_FRAMEERROR = 0x40; // Framing/CRC Error
411: static const uint8 SR1_RXOVERRUN = 0x20; // Rx Overrun
412: static const uint8 SR1_PARITYERROR = 0x10; // Parity Error
413: static const uint8 SR1_RESIDUEMASK = 0x0e; // Residue Code 2-0
414: static const uint8 SR1_ALL_SENT = 0x01; // All Sent
415: // RR1
416: static const uint8 RR1_ENDOFFRAME = SR1_ENDOFFRAME;
417: static const uint8 RR1_FRAMEERROR = SR1_FRAMEERROR;
418: static const uint8 RR1_RXOVERRUN = SR1_RXOVERRUN;
419: static const uint8 RR1_PARITYERROR = SR1_PARITYERROR;
420: static const uint8 RR1_RESIDUEMASK = SR1_RESIDUEMASK;
421: static const uint8 RR1_ALL_SENT = SR1_ALL_SENT;
422:
423: // b7 b6 b5 b4 b3 b2 b1 b0
424: // +---------+----+----+----+----+----+----+
425: // RR3A | 0 | RxA| TxA| ESA| RxB| TxB| ESB|
426: // +---------+----+----+----+----+----+----+
427: static const uint8 RR3_RXA = 0x20; // Channel A Rx Int. Pending
428: static const uint8 RR3_TXA = 0x10; // Channel A Tx Int. Pending
429: static const uint8 RR3_ESA = 0x08; // Channel A E/S Int. Pending
430: static const uint8 RR3_RXB = 0x04; // Channel B Rx Int. Pending
431: static const uint8 RR3_TXB = 0x02; // Channel B Tx Int. Pending
432: static const uint8 RR3_ESB = 0x01; // Channel B E/S Int. Pending
433:
434: public:
435: // 2チャンネル分
436: std::array<MPSCCChan, 2> chan {};
437:
438: // CR2 付近
439: uint8 intdma_mode {};
440: static const uint8 INTDMA_INT_INT = 0; // Both channel INT
441: static const uint8 INTDMA_DMA_INT = 1; // ChA DMA, ChB INT
442: static const uint8 INTDMA_DMA_DMA = 2; // Both channel DMA
443: bool priority_select {};
444: uint8 int_mode {};
445: static const uint8 INTMODE_85_1 = 0;
446: static const uint8 INTMODE_85_2 = 1;
447: static const uint8 INTMODE_86 = 2;
448: // 割り込み時にベクタを出力するなら true。
449: // CR2A の VM は出力なら %1、WR9 の NV(Non Vector) は出力しない時 %1。
450: bool vectored_mode {};
451: bool syncb {};
452:
453: // WR9 付近
454: uint8 wr9_cmd {}; // WR9 の b6,7
455: bool sav_vis {}; // uPD7201 なら CR1 SAV、Z8530 なら WR9 VIS
456: bool disable_lower_chain {};
457: bool master_int_enable {};
458: bool status_high_low {};
459:
460: // ベクタに割り込み要因(3bit) を入れるかどうかは、
461: // CR1 なら Status Affects Vector、
462: // WR9 なら Vector Includes Status が担当。
463: // どこに (どの順で) 入れるかは CR2A INT Mode か WR9 bit4 で指定する。
464: enum {
465: VIS_FIXED = 0,
466: VIS_432, // uPD7201: SAV = %1 && CR2A INT Mode = %00 or %01
467: VIS_210, // uPD7201: SAV = %1 && CR2A INT Mode = %10
468: VIS_321, // Z8530: VIS = %1 && WR9 SHSL = %0
469: VIS_456, // Z8530: VIS = %1 && WR9 SHSL = %1 (456; 向きに注意)
470: } vis {};
471:
472: // b7 b6 b5 b4 b3 b2 b1 b0
473: // +---------------------------------------+
474: // CR2B | Vector |
475: // WR2 +---------------------------------------+
476: //
477: // b7 b6 b5 b4 b3 b2 b1 b0
478: // +---------------------------------------+
479: // RR2A | Vector (WR2 に書いた値) |
480: // +---------------------------------------+
481: //
482: // +---------------------------------------+
483: // SR2B | Vector (割り込み要因で変化した値) |
484: // RR2B +---------------------------------------+
485: uint vector {};
486:
487: // 割り込み要因
488: static const uint VS_TxB = 0;
489: static const uint VS_ESB = 1;
490: static const uint VS_RxB = 2;
491: static const uint VS_SPB = 3;
492: static const uint VS_TxA = 4;
493: static const uint VS_ESA = 5;
494: static const uint VS_RxA = 6;
495: static const uint VS_SPA = 7;
496: static const uint VS_none = 8; // 割り込みなし
497: };
498:
499: class MPSCCDevice : public IODevice
500: {
501: using inherited = IODevice;
502: protected:
503: // 割り込みペンディングビット。chan.intpend で使用する。
504: static const uint INTPEND_TX = 0x01;
505: static const uint INTPEND_ES = 0x02;
506: static const uint INTPEND_RX = 0x04;
507: static const uint INTPEND_SP = 0x08;
508:
509: // 今のところ SIO, SCC どちらもシリアルポートはチャンネル 0
510: static const int COM_CH = 0;
511:
512: public:
1.1.1.3 root 513: MPSCCDevice();
1.1 root 514: ~MPSCCDevice() override;
515:
516: bool Create() override;
517: void SetLogLevel(int loglevel_) override;
518: bool Init() override;
519:
520: // 1バイト受信 (送信側デバイスが呼ぶ)
521: virtual bool Rx(int ch, uint32 data);
522:
523: protected:
524: // 指定のレジスタ名を返す
1.1.1.5 root 525: virtual const char *CRName(const MPSCCChan&, uint n) const = 0;
526: virtual const char *SRName(const MPSCCChan&, uint n) const = 0;
1.1 root 527: // 現在のレジスタ名を返す
528: const char *CRName(const MPSCCChan& chan) const {
529: return CRName(chan, chan.ptr);
530: }
531: const char *SRName(const MPSCCChan& chan) const {
532: return SRName(chan, chan.ptr);
533: }
534:
535: // チャンネルリセットの共通部
536: void ResetChannelCommon(MPSCCChan&);
537:
1.1.1.5 root 538: // BusIO インタフェース
539: static const uint32 NPORT = 4;
540: bool PokePort(uint32 offset, uint32 data);
541:
1.1 root 542: // レジスタアクセス
1.1.1.2 root 543: static uint8 GetCR0(const MPSCCChan&);
544: static void SetCR3(MPSCCChan&, uint32 data);
545: static uint8 GetCR3(const MPSCCChan&);
546: static void SetCR4(MPSCCChan&, uint32 data);
547: static uint8 GetCR4(const MPSCCChan&);
548: static void SetCR5(MPSCCChan&, uint32 data);
549: static uint8 GetCR5(const MPSCCChan&);
1.1 root 550: uint8 GetSR2B() const;
551: void WriteCR3(MPSCCChan&, uint32 data);
552: void WriteCR4(MPSCCChan&, uint32 data);
553: void WriteCR5(MPSCCChan&, uint32 data);
554: void WriteCR6(MPSCCChan&, uint32 data);
555: void WriteCR7(MPSCCChan&, uint32 data);
556:
557: uint8 ReadData(MPSCCChan&);
558: void WriteData(MPSCCChan&, uint32 data);
559: uint8 PeekData(const MPSCCChan&) const;
560:
561: void SendAbort(MPSCCChan&);
562: void ResetESIntr(MPSCCChan&);
563: void EnableIntrOnNextRx(MPSCCChan&);
564: void ResetTxIntrPending(MPSCCChan&);
565: void ErrorReset(MPSCCChan&);
566: void ResetHighestIUS(MPSCCChan&);
567:
568: // 1バイト送信
569: virtual void Tx(int ch, uint32 data) = 0;
570:
571: // シリアルから1バイト受信のメッセージとイベントコールバック
572: void HostRxCallback();
1.1.1.4 root 573: void RxMessage(MessageID, uint32);
1.1 root 574: void RxCallback(Event&);
575:
576: // 送受信関連
577: void TrySend(MPSCCChan&);
578: void SetTxPeriod(MPSCCChan&);
579: void SetRxPeriod(MPSCCChan&);
580: void TxCallback(Event&);
581:
582: // 割り込み
583: void ChangeInterrupt();
584: // ペンディングのうち最も優先度の高い割り込み要因 (VS_*) を返す
585: virtual uint GetHighestInt() const = 0;
586:
587: // "9600,N,8,1" みたいなのを返す
588: std::string GetParamStr(const MPSCCChan& chan) const;
589:
1.1.1.2 root 590: void ChangeBaudrate(MPSCCChan&);
591: static int GetClkRate(uint8);
592: int AdditionalBits(MPSCCChan&, bool enable);
593: int GetStopBits(MPSCCChan&, bool enable);
594:
1.1 root 595: // モニタの下請け
596: int MonitorUpdateCR345(TextScreen&, int x, int y, uint8, uint8, uint8);
597: void MonitorUpdateSR1(TextScreen&, int x, int y, uint8 sr1);
598: void MonitorReg(TextScreen&, int x, int y,
599: uint32 reg, const char * const *names);
600:
601: MPSCC mpscc {};
602:
603: // 送受信用イベント
604: std::array<Event, 2> txevent {};
605: std::array<Event, 2> rxevent {};
606:
607: // シリアルポート。
608: // 本当は共通層でやることではないがどう考えても同じコードになるので。
609: std::unique_ptr<HostCOMDevice> hostcom /*{}*/;
610:
611: // SR0 のログ対策 (sio.cpp::ReadCtrl 参照)
612: int sr0_logphase {};
613: uint32 sr0_lastread {};
1.1.1.3 root 614:
615: InterruptDevice *interrupt {};
616:
1.1.1.6 ! root 617: // モニタ
! 618: Monitor *monitor {};
1.1 root 619: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.