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