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