2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ uPD1990A / uPD4990A ]
15 DLL_PREFIX_I struct cur_time_s cur_time;
18 void UPD1990A::initialize()
21 __HAS_UPD4990A = osd->check_feature(_T("HAS_UPD4990A"));
22 if(__HAS_UPD4990A) set_device_name(_T("uPD4990A_RTC"));
24 get_host_time(&cur_time);
27 register_event(this, EVENT_1SEC, 1000000.0, true, ®ister_id_1sec);
31 void UPD1990A::write_signal(int id, uint32_t data, uint32_t mask)
33 if(id == SIG_UPD1990A_CLK) {
34 bool next = ((data & mask) != 0);
36 if((mode & 0x0f) == 1) {
58 dout = (uint32_t)(shift_data & 1);
60 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
63 if(__HAS_UPD4990A) shift_cmd = (shift_cmd >> 1) | (din ? 8 : 0);
67 } else if(id == SIG_UPD1990A_STB) {
68 bool next = ((data & mask) != 0);
69 if(!stb && next/* && !clk*/) {
73 mode = shift_cmd | 0x80;
86 uint64_t tmp = shift_data;
87 cur_time.second = FROM_BCD(tmp);
89 cur_time.minute = FROM_BCD(tmp);
91 cur_time.hour = FROM_BCD(tmp);
93 cur_time.day = FROM_BCD(tmp);
95 cur_time.day_of_week = tmp & 0x0f;
97 cur_time.month = tmp & 0x0f;
102 cur_time.year = FROM_BCD(tmp);
103 cur_time.update_year();
104 cur_time.update_day_of_week();
112 // after all bits are read, lsb of second data can be read
113 shift_data = TO_BCD(cur_time.second);
115 //#ifdef HAS_UPD4990A
119 shift_data |= TO_BCD(cur_time.year);
124 shift_data |= cur_time.month;
126 shift_data |= cur_time.day_of_week;
128 shift_data |= TO_BCD(cur_time.day);
130 shift_data |= TO_BCD(cur_time.hour);
132 shift_data |= TO_BCD(cur_time.minute);
134 shift_data |= TO_BCD(cur_time.second);
136 dout = (uint32_t)(shift_data & 1);
138 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
143 //#ifdef HAS_UPD4990A
150 if(!__HAS_UPD4990A && ((mode & 0x0f) > 0x06)) break;
152 if(tpmode != (mode & 0x0f)) {
153 if(outputs_tp.count != 0) {
154 static const double tbl[] = {
155 1000000.0 / 128.0, // 64Hz
156 1000000.0 / 512.0, // 256Hz
157 1000000.0 / 2048.0, // 2048Hz
158 //#ifdef HAS_UPD4990A
159 1000000.0 / 4098.0, // 4096Hz
161 1000000.0 * 10, // 10sec
162 1000000.0 * 30, // 30sec
163 1000000.0 * 60 // 60sec
166 if(register_id_tp != -1) {
167 cancel_event(this, register_id_tp);
170 register_event(this, EVENT_TP, tbl[(mode & 0x0f) - 4], true, ®ister_id_tp);
172 tpmode = mode & 0x0f;
178 // reset counter hold
179 switch(mode & 0x0f) {
185 cancel_event(this, register_id_1sec);
186 register_event(this, EVENT_1SEC, 1000000.0, true, ®ister_id_1sec);
193 } else if(id == SIG_UPD1990A_CMD) {
194 cmd = (cmd & ~mask) | (data & mask);
196 } else if(id == SIG_UPD1990A_C0) {
197 cmd = (cmd & ~1) | (data & mask ? 1 : 0);
199 } else if(id == SIG_UPD1990A_C1) {
200 cmd = (cmd & ~2) | (data & mask ? 2 : 0);
202 } else if(id == SIG_UPD1990A_C2) {
203 cmd = (cmd & ~4) | (data & mask ? 4 : 0);
205 } else if(id == SIG_UPD1990A_DIN) {
206 din = ((data & mask) != 0);
210 void UPD1990A::event_callback(int event_id, int err)
212 if(event_id == EVENT_1SEC) {
213 if(cur_time.initialized) {
215 cur_time.increment();
218 dout_changed = false;
220 dout = cur_time.second & 1;
221 write_signals(&outputs_dout, (cur_time.second & 1) ? 0xffffffff : 0);
224 get_host_time(&cur_time); // resync
225 cur_time.initialized = true;
227 } else if(event_id == EVENT_TP) {
228 write_signals(&outputs_tp, tp ? 0xffffffff : 0);
233 #define STATE_VERSION 2
235 #include "../statesub.h"
237 void UPD1990A::decl_state()
239 enter_decl_state(STATE_VERSION);
241 DECL_STATE_ENTRY_CUR_TIME_T(cur_time);
242 DECL_STATE_ENTRY_INT32(register_id_1sec);
243 DECL_STATE_ENTRY_UINT8(cmd);
244 DECL_STATE_ENTRY_UINT8(mode);
245 DECL_STATE_ENTRY_UINT8(tpmode);
246 DECL_STATE_ENTRY_UINT64(shift_data);
247 DECL_STATE_ENTRY_BOOL(clk);
248 DECL_STATE_ENTRY_BOOL(stb);
249 DECL_STATE_ENTRY_BOOL(din);
250 DECL_STATE_ENTRY_BOOL(hold);
251 DECL_STATE_ENTRY_BOOL(tp);
252 DECL_STATE_ENTRY_UINT32(dout);
253 DECL_STATE_ENTRY_BOOL(dout_changed);
254 DECL_STATE_ENTRY_INT32(register_id_tp);
255 if(__HAS_UPD4990A) DECL_STATE_ENTRY_UINT8(shift_cmd);
259 void UPD1990A::save_state(FILEIO* state_fio)
261 if(state_entry != NULL) {
262 state_entry->save_state(state_fio);
265 // state_fio->FputUint32(STATE_VERSION);
266 // state_fio->FputInt32(this_device_id);
268 // cur_time.save_state((void *)state_fio);
269 // state_fio->FputInt32(register_id_1sec);
270 // state_fio->FputUint8(cmd);
271 // state_fio->FputUint8(mode);
272 // state_fio->FputUint8(tpmode);
273 // state_fio->FputUint64(shift_data);
274 // state_fio->FputBool(clk);
275 // state_fio->FputBool(stb);
276 // state_fio->FputBool(din);
277 // state_fio->FputBool(hold);
278 // state_fio->FputBool(tp);
279 // state_fio->FputUint32(dout);
280 // state_fio->FputBool(dout_changed);
281 // state_fio->FputInt32(register_id_tp);
282 //#ifdef HAS_UPD4990A
283 // if(__HAS_UPD4990A) state_fio->FputUint8(shift_cmd);
287 bool UPD1990A::load_state(FILEIO* state_fio)
290 if(state_entry != NULL) {
291 mb = state_entry->load_state(state_fio);
293 if(!mb) return false;
295 // if(state_fio->FgetUint32() != STATE_VERSION) {
298 // if(state_fio->FgetInt32() != this_device_id) {
301 // if(!cur_time.load_state((void *)state_fio)) {
304 // register_id_1sec = state_fio->FgetInt32();
305 // cmd = state_fio->FgetUint8();
306 // mode = state_fio->FgetUint8();
307 // tpmode = state_fio->FgetUint8();
308 // shift_data = state_fio->FgetUint64();
309 // clk = state_fio->FgetBool();
310 // stb = state_fio->FgetBool();
311 /// din = state_fio->FgetBool();
312 // hold = state_fio->FgetBool();
313 // tp = state_fio->FgetBool();
314 // dout = state_fio->FgetUint32();
315 // dout_changed = state_fio->FgetBool();
316 // register_id_tp = state_fio->FgetInt32();
317 //#ifdef HAS_UPD4990A
318 // if(__HAS_UPD4990A) shift_cmd = state_fio->FgetUint8();