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);
28 tp_usec = 1.0e6 / 128.0; // 64Hz
32 void UPD1990A::write_signal(int id, uint32_t data, uint32_t mask)
34 static const double tbl[] = {
35 1000000.0 / 128.0, // 64Hz
36 1000000.0 / 512.0, // 256Hz
37 1000000.0 / 2048.0, // 2048Hz
39 1000000.0 / 4096.0, // 4096Hz
41 1000000.0 * 10, // 10sec
42 1000000.0 * 30, // 30sec
43 1000000.0 * 60 // 60sec
46 if(id == SIG_UPD1990A_CLK) {
47 bool next = ((data & mask) != 0);
49 if((mode & 0x0f) == 1) {
71 dout = (uint32_t)(shift_data & 1);
73 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
76 if(__HAS_UPD4990A) shift_cmd = (shift_cmd >> 1) | (din ? 8 : 0);
80 } else if(id == SIG_UPD1990A_STB) {
81 bool next = ((data & mask) != 0);
82 if(!stb && next/* && !clk*/) {
86 mode = shift_cmd | 0x80;
100 uint64_t tmp = shift_data;
101 cur_time.second = FROM_BCD(tmp);
103 cur_time.minute = FROM_BCD(tmp);
105 cur_time.hour = FROM_BCD(tmp);
107 cur_time.day = FROM_BCD(tmp);
109 cur_time.day_of_week = tmp & 0x0f;
111 cur_time.month = tmp & 0x0f;
112 //#ifdef HAS_UPD4990A
116 cur_time.year = FROM_BCD(tmp);
117 cur_time.update_year();
118 cur_time.update_day_of_week();
126 // after all bits are read, lsb of second data can be read
128 //#ifdef HAS_UPD4990A
132 shift_data |= TO_BCD(cur_time.year);
137 shift_data |= cur_time.month;
139 shift_data |= cur_time.day_of_week;
141 shift_data |= TO_BCD(cur_time.day);
143 shift_data |= TO_BCD(cur_time.hour);
145 shift_data |= TO_BCD(cur_time.minute);
147 shift_data |= TO_BCD(cur_time.second);
149 dout = (uint32_t)(shift_data & 1);
151 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
156 //#ifdef HAS_UPD4990A
163 if(!(__HAS_UPD4990A) && ((mode & 0x07) == 0x07)) break;
164 if(tpmode != (mode & 0x0f)) {
165 if(outputs_tp.count != 0) {
166 if(register_id_tp != -1) {
167 cancel_event(this, register_id_tp);
170 if(!(__HAS_UPD4990A) || ((mode & 0x80) == 0)) {
171 tp_usec = tbl[(mode & 0x07) - 4];
173 tp_usec = tbl[(mode & 0x0f) - 4];
175 register_event(this, EVENT_TP, tp_usec, true, ®ister_id_tp);
177 tpmode = mode & 0x0f;
180 // Below are extra commands.
181 case 0x0c: // Int reset
183 write_signals(&outputs_tp, 0);
185 case 0x0d: // Int Start
186 if(register_id_tp == -1) {
188 register_event(this, EVENT_TP, tp_usec, true, ®ister_id_tp);
191 case 0x0e: // Int Stop
192 if(register_id_tp != -1) {
193 cancel_event(this, register_id_tp);
204 // reset counter hold
205 switch(mode & 0x0f) {
211 cancel_event(this, register_id_1sec);
212 register_event(this, EVENT_1SEC, 1000000.0, true, ®ister_id_1sec);
219 } else if(id == SIG_UPD1990A_CMD) {
220 cmd = (cmd & ~mask) | (data & mask);
222 } else if(id == SIG_UPD1990A_C0) {
223 cmd = (cmd & ~1) | (data & mask ? 1 : 0);
225 } else if(id == SIG_UPD1990A_C1) {
226 cmd = (cmd & ~2) | (data & mask ? 2 : 0);
228 } else if(id == SIG_UPD1990A_C2) {
229 cmd = (cmd & ~4) | (data & mask ? 4 : 0);
231 } else if(id == SIG_UPD1990A_DIN) {
232 din = ((data & mask) != 0);
236 void UPD1990A::event_callback(int event_id, int err)
238 if(event_id == EVENT_1SEC) {
239 if(cur_time.initialized) {
241 cur_time.increment();
244 dout_changed = false;
246 dout = cur_time.second & 1;
247 write_signals(&outputs_dout, (cur_time.second & 1) ? 0xffffffff : 0);
250 get_host_time(&cur_time); // resync
251 cur_time.initialized = true;
253 } else if(event_id == EVENT_TP) {
254 write_signals(&outputs_tp, tp ? 0xffffffff : 0);
259 #define STATE_VERSION 3
261 bool UPD1990A::process_state(FILEIO* state_fio, bool loading)
263 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
266 if(!state_fio->StateCheckInt32(this_device_id)) {
269 if(!cur_time.process_state((void *)state_fio, loading)) {
272 state_fio->StateValue(register_id_1sec);
273 state_fio->StateValue(cmd);
274 state_fio->StateValue(mode);
275 state_fio->StateValue(tpmode);
276 state_fio->StateValue(shift_data);
277 state_fio->StateValue(clk);
278 state_fio->StateValue(stb);
279 state_fio->StateValue(din);
280 state_fio->StateValue(hold);
281 state_fio->StateValue(tp);
282 state_fio->StateValue(dout);
283 state_fio->StateValue(dout_changed);
284 state_fio->StateValue(register_id_tp);
286 state_fio->StateValue(shift_cmd);
288 state_fio->StateValue(tp_usec);