OSDN Git Service

30d874471be63df6ba4e79d027a40e54990a4c7b
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd1990a.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2008.04.19-
6
7         [ uPD1990A / uPD4990A ]
8 */
9
10 #include "upd1990a.h"
11
12 #define EVENT_1SEC      0
13 #define EVENT_TP        1
14 #if defined(Q_OS_WIN)
15 DLL_PREFIX_I struct cur_time_s cur_time;
16 #endif
17
18 void UPD1990A::initialize()
19 {
20         DEVICE::initialize();
21         __HAS_UPD4990A = osd->check_feature(_T("HAS_UPD4990A"));
22         if(__HAS_UPD4990A) set_device_name(_T("uPD4990A_RTC"));
23         // initialize rtc
24         get_host_time(&cur_time);
25         
26         // register events
27         register_event(this, EVENT_1SEC, 1000000.0, true, &register_id_1sec);
28         register_id_tp = -1;
29 }
30
31 void UPD1990A::write_signal(int id, uint32_t data, uint32_t mask)
32 {
33         if(id == SIG_UPD1990A_CLK) {
34                 bool next = ((data & mask) != 0);
35                 if(!clk && next) {
36                         if((mode & 0x0f) == 1) {
37                                 uint64_t bit = 1;
38 //#ifdef HAS_UPD4990A
39                                 if(__HAS_UPD4990A) {
40                                         if(mode & 0x80) {
41                                                 bit <<= (52 - 1);
42                                         } else {
43 //#endif
44                                                 bit <<= (40 - 1);
45 //#ifdef HAS_UPD4990A
46                                         }
47                                 } else {
48 //#endif
49                                         bit <<= (40 - 1);
50                                 }                                       
51                                 shift_data >>= 1;
52                                 if(din) {
53                                         shift_data |= bit;
54                                 } else {
55                                         shift_data &= ~bit;
56                                 }
57                                 // output LSB
58                                 dout = (uint32_t)(shift_data & 1);
59                                 dout_changed = true;
60                                 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
61                         }
62 //#ifdef HAS_UPD4990A
63                         if(__HAS_UPD4990A) shift_cmd = (shift_cmd >> 1) | (din ? 8 : 0);
64 //#endif
65                 }
66                 clk = next;
67         } else if(id == SIG_UPD1990A_STB) {
68                 bool next = ((data & mask) != 0);
69                 if(!stb && next/* && !clk*/) {
70 //#ifdef HAS_UPD4990A
71                         if(__HAS_UPD4990A) {
72                                 if(cmd == 7) {
73                                         mode = shift_cmd | 0x80;
74                                 } else {
75 //#endif
76                                         mode = cmd;
77 //#ifdef HAS_UPD4990A
78                                 }
79                         } else {
80                                 mode = cmd;
81                         }
82 //#endif
83                         switch(mode & 0x0f) {
84                         case 0x02:
85                                 {
86                                         uint64_t tmp = shift_data;
87                                         cur_time.second = FROM_BCD(tmp);
88                                         tmp >>= 8;
89                                         cur_time.minute = FROM_BCD(tmp);
90                                         tmp >>= 8;
91                                         cur_time.hour = FROM_BCD(tmp);
92                                         tmp >>= 8;
93                                         cur_time.day = FROM_BCD(tmp);
94                                         tmp >>= 8;
95                                         cur_time.day_of_week = tmp & 0x0f;
96                                         tmp >>= 4;
97                                         cur_time.month = tmp & 0x0f;
98 //#ifdef HAS_UPD4990A
99                                         if(__HAS_UPD4990A) {
100                                                 if(mode & 0x80) {
101                                                         tmp >>= 4;
102                                                         cur_time.year = FROM_BCD(tmp);
103                                                         cur_time.update_year();
104                                                         cur_time.update_day_of_week();
105                                                 }
106                                         }
107 //#endif
108                                 }
109                                 hold = true;
110                                 break;
111                         case 0x03:
112                                 // after all bits are read, lsb of second data can be read
113                                 shift_data = TO_BCD(cur_time.second);
114                                 //shift_data = 0;
115 //#ifdef HAS_UPD4990A
116                                 if(__HAS_UPD4990A) {
117                                         if(mode & 0x80) {
118                                                 shift_data <<= 8;
119                                                 shift_data |= TO_BCD(cur_time.year);
120                                         }
121                                 }
122 //#endif
123                                 shift_data <<= 4;
124                                 shift_data |= cur_time.month;
125                                 shift_data <<= 4;
126                                 shift_data |= cur_time.day_of_week;
127                                 shift_data <<= 8;
128                                 shift_data |= TO_BCD(cur_time.day);
129                                 shift_data <<= 8;
130                                 shift_data |= TO_BCD(cur_time.hour);
131                                 shift_data <<= 8;
132                                 shift_data |= TO_BCD(cur_time.minute);
133                                 shift_data <<= 8;
134                                 shift_data |= TO_BCD(cur_time.second);
135                                 // output LSB
136                                 dout = (uint32_t)(shift_data & 1);
137                                 dout_changed = true;
138                                 write_signals(&outputs_dout, (shift_data & 1) ? 0xffffffff : 0);
139                                 break;
140                         case 0x04:
141                         case 0x05:
142                         case 0x06:
143 //#ifdef HAS_UPD4990A
144                         case 0x07:
145                         case 0x08:
146                         case 0x09:
147                         case 0x0a:
148                         case 0x0b:
149 //#endif
150                                 if(!__HAS_UPD4990A && ((mode & 0x0f) > 0x06)) break;
151
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
160                                                         1000000.0,              // 1sec
161                                                         1000000.0 * 10,         // 10sec
162                                                         1000000.0 * 30,         // 30sec
163                                                         1000000.0 * 60          // 60sec
164 //#endif
165                                                 };
166                                                 if(register_id_tp != -1) {
167                                                         cancel_event(this, register_id_tp);
168                                                         register_id_tp = -1;
169                                                 }
170                                                 register_event(this, EVENT_TP, tbl[(mode & 0x0f) - 4], true, &register_id_tp);
171                                         }
172                                         tpmode = mode & 0x0f;
173                                 }
174                                 break;
175                         default:
176                                 break;
177                         }
178                         // reset counter hold
179                         switch(mode & 0x0f) {
180                         case 0x00:
181                         case 0x01:
182                         case 0x03:
183                                 if(hold) {
184                                         // restart event
185                                         cancel_event(this, register_id_1sec);
186                                         register_event(this, EVENT_1SEC, 1000000.0, true, &register_id_1sec);
187                                         hold = false;
188                                 }
189                                 break;
190                         }
191                 }
192                 stb = next;
193         } else if(id == SIG_UPD1990A_CMD) {
194                 cmd = (cmd & ~mask) | (data & mask);
195                 cmd &= 7;
196         } else if(id == SIG_UPD1990A_C0) {
197                 cmd = (cmd & ~1) | (data & mask ? 1 : 0);
198                 cmd &= 7;
199         } else if(id == SIG_UPD1990A_C1) {
200                 cmd = (cmd & ~2) | (data & mask ? 2 : 0);
201                 cmd &= 7;
202         } else if(id == SIG_UPD1990A_C2) {
203                 cmd = (cmd & ~4) | (data & mask ? 4 : 0);
204                 cmd &= 7;
205         } else if(id == SIG_UPD1990A_DIN) {
206                 din = ((data & mask) != 0);
207         }
208 }
209
210 void UPD1990A::event_callback(int event_id, int err)
211 {
212         if(event_id == EVENT_1SEC) {
213                 if(cur_time.initialized) {
214                         if(!hold) {
215                                 cur_time.increment();
216                         }
217                         if(dout_changed) {
218                                 dout_changed = false;
219                         } else {
220                                 dout = cur_time.second & 1;
221                                 write_signals(&outputs_dout, (cur_time.second & 1) ? 0xffffffff : 0);
222                         }
223                 } else {
224                         get_host_time(&cur_time);       // resync
225                         cur_time.initialized = true;
226                 }
227         } else if(event_id == EVENT_TP) {
228                 write_signals(&outputs_tp, tp ? 0xffffffff : 0);
229                 tp = !tp;
230         }
231 }
232
233 #define STATE_VERSION   2
234
235 #include "../statesub.h"
236
237 void UPD1990A::decl_state()
238 {
239         enter_decl_state(STATE_VERSION);
240         
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);
256
257         leave_decl_state();
258 }
259 void UPD1990A::save_state(FILEIO* state_fio)
260 {
261         if(state_entry != NULL) {
262                 state_entry->save_state(state_fio);
263         }
264         
265 //      state_fio->FputUint32(STATE_VERSION);
266 //      state_fio->FputInt32(this_device_id);
267         
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);
284 //#endif
285 }
286
287 bool UPD1990A::load_state(FILEIO* state_fio)
288 {
289         bool mb = false;
290         if(state_entry != NULL) {
291                 mb = state_entry->load_state(state_fio);
292         }
293         if(!mb) return false;
294
295 //      if(state_fio->FgetUint32() != STATE_VERSION) {
296 //              return false;
297 //      }
298 //      if(state_fio->FgetInt32() != this_device_id) {
299 //              return false;
300 //      }
301 //      if(!cur_time.load_state((void *)state_fio)) {
302 //              return false;
303 //      }
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();
319 //#endif
320         return true;
321 }
322