|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2017 [email protected] ! 4: // ! 5: ! 6: #pragma once ! 7: ! 8: #include "device.h" ! 9: #include "scheduler.h" ! 10: ! 11: struct MFP ! 12: { ! 13: static const int GPIP = 0; // $E88001 ! 14: static const int AER = 1; // $E88003 ! 15: static const int DDR = 2; // $E88005 ! 16: static const int IERA = 3; // $E88007 ! 17: static const int IERB = 4; // $E88009 ! 18: static const int IPRA = 5; // $E8800B ! 19: static const int IPRB = 6; // $E8800D ! 20: static const int ISRA = 7; // $E8800F ! 21: static const int ISRB = 8; // $E88011 ! 22: static const int IMRA = 9; // $E88013 ! 23: static const int IMRB = 10; // $E88015 ! 24: static const int VR = 11; // $E88017 ! 25: static const int TACR = 12; // $E88019 ! 26: static const int TBCR = 13; // $E8801B ! 27: static const int TCDCR = 14; // $E8801D ! 28: static const int TADR = 15; // $E8801F ! 29: static const int TBDR = 16; // $E88021 ! 30: static const int TCDR = 17; // $E88023 ! 31: static const int TDDR = 18; // $E88025 ! 32: static const int SCR = 19; // $E88027 ! 33: static const int UCR = 20; // $E88029 ! 34: static const int RSR = 21; // $E8802B ! 35: static const int TSR = 22; // $E8802D ! 36: static const int UDR = 23; // $E8802F ! 37: ! 38: union ir16 { ! 39: uint16 w; ! 40: struct { ! 41: #if BYTE_ORDER == LITTLE_ENDIAN ! 42: uint8 b, a; ! 43: #else ! 44: uint8 a, b; ! 45: #endif ! 46: }; ! 47: }; ! 48: ! 49: // ハードウェア未実装ビットは書き込み時に '0' にする ! 50: ! 51: uint8 gpip; ! 52: uint8 aer; ! 53: uint8 ddr; ! 54: static const int GPIP_HSYNC = 7; ! 55: static const int GPIP_CIRQ = 6; ! 56: // 5 は常に '1' ! 57: static const int GPIP_VDISP = 4; ! 58: static const int GPIP_FMIRQ = 3; ! 59: static const int GPIP_POWSW = 2; ! 60: static const int GPIP_EXPON = 1; ! 61: static const int GPIP_ALARM = 0; ! 62: ! 63: ir16 ier; ! 64: ir16 ipr; ! 65: ir16 isr; ! 66: ir16 imr; ! 67: uint8 vr; // V7 V6 V5 V4 S --- --- --- ! 68: ! 69: // TDR のカウンタをメインカウンタと呼び、このメインカウンタを ! 70: // 1減らすためのカウンタをプリスケーラカウンタと呼ぶ。 ! 71: // 実際のハードウェアは 4MHz のクロック入力ごとにプリスケーラカウンタを ! 72: // カウントしていき指定回数カウントすればメインカウンタを1減らすのだが、 ! 73: // この実装ではどちらのカウンタも持たず、タイマー開始時刻と現在時刻で ! 74: // 管理する。そのため、メインカウンタもプリスケーラカウンタも必要なら ! 75: // この時間差から求める。 ! 76: // ! 77: // X680x0 の MFP は 4MHz なので、1クロックは 0.25 usec。 ! 78: // TxCR = 1 の時プリスケール回数は 10 なので、入力クロック10回 ! 79: // (2.5usec) ごとにメインカウンタを 1 減らす。 ! 80: // TxDR = 5 から開始すれば 50 カウント (12.5 usec) 後にタイムアップする。 ! 81: // そのためタイマー開始時から現在 3 usec 経過していれば 3 / 0.25 = 12 で ! 82: // 総入力クロックは12回、メインカウンタは 1 減っており、プリスケール ! 83: // カウントは10回中残り 8回を指していることになる。 ! 84: ! 85: uint8 tcr[4]; // --- --- --- RST AC3 AC2 AC1 AC0 : TACR ! 86: // --- --- --- RST BC3 BC2 BC1 BC0 : TBCR ! 87: // --- CC2 CC1 CC0 --- DC2 DC1 DC0 : TCDCR ! 88: ! 89: // tdr はカウンタの設定値。 ! 90: // タイマー停止中に TxDR に書き込まれると、initial_tdr に即反映される。 ! 91: // タイマー動作中に TxDR に書き込まれると、initial_tdr に反映されるのは ! 92: // 次のリロードタイミング。 ! 93: uint8 tdr[4]; ! 94: ! 95: // initial_tdr はカウントダウン開始時点での TxDR の値。 ! 96: // カウンタが 1 から 0 になるタイミングで tdr の値をリロードする。 ! 97: // tdr に $00 を書き込むと 256 カウントになるため、 ! 98: // initial_tdr は 1..256 の値をとる。 ! 99: uint initial_tdr[4]; ! 100: ! 101: uint64 timer_start[4]; // タイマー開始時の仮想時刻 ! 102: ! 103: uint8 scr; ! 104: uint8 ucr; // CLK WLI WLO STI STO PE E/O --- ! 105: uint8 rsr; ! 106: uint8 tsr; ! 107: uint8 udr; ! 108: ! 109: }; ! 110: ! 111: class MFPDevice ! 112: : public IODevice ! 113: { ! 114: typedef IODevice inherited; ! 115: ! 116: static const int baseaddr = 0xe88000; ! 117: ! 118: public: ! 119: MFPDevice(); ! 120: virtual ~MFPDevice(); ! 121: ! 122: virtual void ResetSoft(); ! 123: ! 124: virtual uint64 Read8(uint32 addr); ! 125: virtual uint64 Read16(uint32 addr); ! 126: virtual uint64 Write8(uint32 addr, uint32 data); ! 127: virtual uint64 Write16(uint32 addr, uint32 data); ! 128: virtual uint64 Peek8(uint32 addr); ! 129: virtual bool MonitorUpdate(); ! 130: ! 131: // VDisp 入力 ! 132: void SetVDisp(bool vdisp); ! 133: ! 134: private: ! 135: bool IsTimerIntrEnable(uint ch) const; ! 136: void SetTCR(int ch, uint32 data); ! 137: uint8 GetTDR(int ch); ! 138: void SetTDR(int ch, uint32 data); ! 139: ! 140: // GPIP の信号状態をセットする ! 141: void SetGPIP(int num, bool val); ! 142: ! 143: // タイマーイベントコールバック ! 144: void TimerCallback(int arg); ! 145: ! 146: struct MFP mfp {}; ! 147: Event event[4] {}; ! 148: ! 149: static const char *intrname[]; ! 150: static const char *gpipname[]; ! 151: static const int prescale_ns[8]; ! 152: static const char *prescale_str[8]; ! 153: static const int timer_vector[4]; ! 154: }; ! 155: ! 156: extern MFPDevice *gMFP;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.