2 Skelton for retropc emulator
\r
4 Author : Takeda.Toshiya
\r
7 [ uPD1990A / uPD4990A ]
\r
10 #include "upd1990a.h"
\r
11 #include "../fileio.h"
\r
13 #define EVENT_1SEC 0
\r
16 void UPD1990A::initialize()
\r
19 emu->get_host_time(&cur_time);
\r
22 register_event(this, EVENT_1SEC, 1000000.0, true, ®ister_id_1sec);
\r
23 register_id_tp = -1;
\r
26 void UPD1990A::write_signal(int id, uint32 data, uint32 mask)
\r
28 if(id == SIG_UPD1990A_CLK) {
\r
29 bool next = ((data & mask) != 0);
\r
31 if((mode & 0x0f) == 1) {
\r
49 dout = (uint32)(shift_data & 1);
\r
50 dout_changed = true;
\r
51 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
\r
54 shift_cmd = (shift_cmd >> 1) | (din ? 8 : 0);
\r
58 } else if(id == SIG_UPD1990A_STB) {
\r
59 bool next = ((data & mask) != 0);
\r
60 if(!stb && next && !clk) {
\r
63 mode = shift_cmd | 0x80;
\r
70 switch(mode & 0x0f) {
\r
73 uint64 tmp = shift_data;
\r
74 cur_time.second = FROM_BCD(tmp);
\r
76 cur_time.minute = FROM_BCD(tmp);
\r
78 cur_time.hour = FROM_BCD(tmp);
\r
80 cur_time.day = FROM_BCD(tmp);
\r
82 cur_time.day_of_week = tmp & 0x0f;
\r
84 cur_time.month = tmp & 0x0f;
\r
88 cur_time.year = FROM_BCD(tmp);
\r
89 cur_time.update_year();
\r
90 cur_time.update_day_of_week();
\r
97 // after all bits are read, lsb of second data can be read
\r
98 shift_data = TO_BCD(cur_time.second);
\r
100 #ifdef HAS_UPD4990A
\r
103 shift_data |= TO_BCD(cur_time.year);
\r
107 shift_data |= cur_time.month;
\r
109 shift_data |= cur_time.day_of_week;
\r
111 shift_data |= TO_BCD(cur_time.day);
\r
113 shift_data |= TO_BCD(cur_time.hour);
\r
115 shift_data |= TO_BCD(cur_time.minute);
\r
117 shift_data |= TO_BCD(cur_time.second);
\r
119 dout = (uint32)(shift_data & 1);
\r
120 dout_changed = true;
\r
121 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
\r
126 #ifdef HAS_UPD4990A
\r
133 if(tpmode != (mode & 0x0f)) {
\r
134 if(outputs_tp.count != 0) {
\r
135 static const double tbl[] = {
\r
136 1000000.0 / 128.0, // 64Hz
\r
137 1000000.0 / 512.0, // 256Hz
\r
138 1000000.0 / 2048.0, // 2048Hz
\r
139 #ifdef HAS_UPD4990A
\r
140 1000000.0 / 4098.0, // 4096Hz
\r
142 1000000.0 * 10, // 10sec
\r
143 1000000.0 * 30, // 30sec
\r
144 1000000.0 * 60 // 60sec
\r
147 if(register_id_tp != -1) {
\r
148 cancel_event(this, register_id_tp);
\r
149 register_id_tp = -1;
\r
151 register_event(this, EVENT_TP, tbl[(mode & 0x0f) - 4], true, ®ister_id_tp);
\r
153 tpmode = mode & 0x0f;
\r
157 // reset counter hold
\r
158 switch(mode & 0x0f) {
\r
164 cancel_event(this, register_id_1sec);
\r
165 register_event(this, EVENT_1SEC, 1000000.0, true, ®ister_id_1sec);
\r
172 } else if(id == SIG_UPD1990A_CMD) {
\r
173 cmd = (cmd & ~mask) | (data & mask);
\r
175 } else if(id == SIG_UPD1990A_C0) {
\r
176 cmd = (cmd & ~1) | (data & mask ? 1 : 0);
\r
178 } else if(id == SIG_UPD1990A_C1) {
\r
179 cmd = (cmd & ~2) | (data & mask ? 2 : 0);
\r
181 } else if(id == SIG_UPD1990A_C2) {
\r
182 cmd = (cmd & ~4) | (data & mask ? 4 : 0);
\r
184 } else if(id == SIG_UPD1990A_DIN) {
\r
185 din = ((data & mask) != 0);
\r
189 void UPD1990A::event_callback(int event_id, int err)
\r
191 if(event_id == EVENT_1SEC) {
\r
192 if(cur_time.initialized) {
\r
194 cur_time.increment();
\r
197 dout_changed = false;
\r
199 dout = cur_time.second & 1;
\r
200 write_signals(&outputs_dout, (cur_time.second & 1) ? 0xffffffff : 0);
\r
203 emu->get_host_time(&cur_time); // resync
\r
204 cur_time.initialized = true;
\r
206 } else if(event_id == EVENT_TP) {
\r
207 write_signals(&outputs_tp, tp ? 0xffffffff : 0);
\r
212 #define STATE_VERSION 2
\r
214 void UPD1990A::save_state(FILEIO* state_fio)
\r
216 state_fio->FputUint32(STATE_VERSION);
\r
217 state_fio->FputInt32(this_device_id);
\r
219 cur_time.save_state((void *)state_fio);
\r
220 state_fio->FputInt32(register_id_1sec);
\r
221 state_fio->FputUint8(cmd);
\r
222 state_fio->FputUint8(mode);
\r
223 state_fio->FputUint8(tpmode);
\r
224 state_fio->FputUint64(shift_data);
\r
225 state_fio->FputBool(clk);
\r
226 state_fio->FputBool(stb);
\r
227 state_fio->FputBool(din);
\r
228 state_fio->FputBool(hold);
\r
229 state_fio->FputBool(tp);
\r
230 state_fio->FputUint32(dout);
\r
231 state_fio->FputBool(dout_changed);
\r
232 state_fio->FputInt32(register_id_tp);
\r
233 #ifdef HAS_UPD4990A
\r
234 state_fio->FputUint8(shift_cmd);
\r
238 bool UPD1990A::load_state(FILEIO* state_fio)
\r
240 if(state_fio->FgetUint32() != STATE_VERSION) {
\r
243 if(state_fio->FgetInt32() != this_device_id) {
\r
246 if(!cur_time.load_state((void *)state_fio)) {
\r
249 register_id_1sec = state_fio->FgetInt32();
\r
250 cmd = state_fio->FgetUint8();
\r
251 mode = state_fio->FgetUint8();
\r
252 tpmode = state_fio->FgetUint8();
\r
253 shift_data = state_fio->FgetUint64();
\r
254 clk = state_fio->FgetBool();
\r
255 stb = state_fio->FgetBool();
\r
256 din = state_fio->FgetBool();
\r
257 hold = state_fio->FgetBool();
\r
258 tp = state_fio->FgetBool();
\r
259 dout = state_fio->FgetUint32();
\r
260 dout_changed = state_fio->FgetBool();
\r
261 register_id_tp = state_fio->FgetInt32();
\r
262 #ifdef HAS_UPD4990A
\r
263 shift_cmd = state_fio->FgetUint8();
\r