|
|
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:
1.1.1.2 ! root 135: // アドレスデコーダ
! 136: uint64 Decoder(uint32 addr) const;
! 137:
1.1 root 138: bool IsTimerIntrEnable(uint ch) const;
139: void SetTCR(int ch, uint32 data);
1.1.1.2 ! root 140: uint8 GetTDR(int ch) const;
1.1 root 141: void SetTDR(int ch, uint32 data);
142:
143: // GPIP の信号状態をセットする
144: void SetGPIP(int num, bool val);
145:
146: // タイマーイベントコールバック
147: void TimerCallback(int arg);
148:
149: struct MFP mfp {};
150: Event event[4] {};
151:
152: static const char *intrname[];
153: static const char *gpipname[];
154: static const int prescale_ns[8];
155: static const char *prescale_str[8];
156: static const int timer_vector[4];
157: };
158:
1.1.1.2 ! root 159: extern std::unique_ptr<MFPDevice> gMFP;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.