OSDN Git Service

[VM][DEVICE][WIP] Updating State functions.Still cause FTBFS.
[csp-qt/common_source_project-fm7.git] / source / src / vm / msm58321_base.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2008.05.02-
6
7         [ MSM58321/MSM5832 ]
8 */
9
10 #include "msm58321.h"
11
12 #define EVENT_BUSY      0
13 #define EVENT_INC       1
14 #define EVENT_PULSE     2
15
16 #if defined(Q_OS_WIN)
17 DLL_PREFIX_I struct cur_time_s cur_time;
18 #endif
19
20 void MSM58321_BASE::initialize()
21 {
22         DEVICE::initialize();
23         // init rtc
24         memset(regs, 0, sizeof(regs));
25         regs[5] = 8; // 24h
26         regs[15] = 0x0f;
27         wreg = regnum = 0;
28         cs = true;
29         rd = wr = addr_wr = busy = hold = false;
30         count_1024hz = count_1s = count_1m = count_1h = 0;
31         
32         get_host_time(&cur_time);
33         read_from_cur_time();
34         
35         // register events
36 //#ifdef HAS_MSM5832
37 //      register_event(this, EVENT_INC, 1000000.0, true, &register_id);
38 //#else
39 //      register_event(this, EVENT_BUSY, 1000000.0, true, &register_id);
40 //#endif
41         register_event(this, EVENT_PULSE, 1000000.0 / 8192.0, true, NULL);      // 122.1 usec
42 }
43
44 void MSM58321_BASE::event_callback(int event_id, int err)
45 {
46         if(event_id == EVENT_BUSY) {
47                 set_busy(true);
48                 register_event(this, EVENT_INC, 430, false, NULL);
49         } else if(event_id == EVENT_INC) {
50                 if(cur_time.initialized) {
51                         cur_time.increment();
52                 } else {
53                         get_host_time(&cur_time);       // resync
54                         cur_time.initialized = true;
55                 }
56                 if(!hold) {
57                         read_from_cur_time();
58                         if(regnum <= 12) {
59                                 output_data();
60                         }
61                 }
62                 set_busy(false);
63         } else if(event_id == EVENT_PULSE) {
64                 if(++count_1024hz == 4) {
65                         count_1024hz = 0;
66                         regs[15] ^= 1;
67                 }
68                 if(++count_1s == 8192) {
69                         count_1s = 0;
70                         regs[15] &= ~2;
71                 } else {
72                         regs[15] |= 2;
73                 }
74                 if(++count_1m == (60 * 8192)) {
75                         count_1m = 0;
76                         regs[15] &= ~4;
77                 } else {
78                         regs[15] |= 4;
79                 }
80                 if(++count_1h == (3600 * 8192)) {
81                         count_1h = 0;
82                         regs[15] &= ~8;
83                 } else {
84                         regs[15] |= 8;
85                 }
86                 regs[14] = regs[15];
87                 if(regnum == 14 || regnum == 15) {
88                         output_data();
89                 }
90         }
91 }
92
93 void MSM58321_BASE::read_from_cur_time()
94 {
95         // update clock
96         int hour = (regs[5] & 8) ? cur_time.hour : (cur_time.hour % 12);
97         int ampm = (cur_time.hour > 11) ? 4 : 0;
98         
99         regs[ 0] = TO_BCD_LO(cur_time.second);
100         regs[ 1] = TO_BCD_HI(cur_time.second);
101         regs[ 2] = TO_BCD_LO(cur_time.minute);
102         regs[ 3] = TO_BCD_HI(cur_time.minute);
103         regs[ 4] = TO_BCD_LO(hour);
104         regs[ 5] = TO_BCD_HI(hour) | ampm | (regs[5] & 8);
105         regs[ 6] = cur_time.day_of_week;
106         regs[ 7] = TO_BCD_LO(cur_time.day - start_day);
107         regs[ 8] = TO_BCD_HI(cur_time.day - start_day) | (regs[8] & 0x0c);
108         regs[ 9] = TO_BCD_LO(cur_time.month);
109         regs[10] = TO_BCD_HI(cur_time.month);
110         regs[11] = TO_BCD_LO(cur_time.year - start_year);
111         regs[12] = TO_BCD_HI(cur_time.year - start_year);
112 }
113
114 void MSM58321_BASE::write_to_cur_time()
115 {
116         cur_time.second = regs[0] + (regs[1] & 7) * 10;
117         cur_time.minute = regs[2] + (regs[3] & 7) * 10;
118         cur_time.hour = regs[4] + (regs[5] & 3) * 10;
119         if(!(regs[5] & 8)) {
120                 cur_time.hour %= 12;
121                 if(regs[5] & 4) {
122                         cur_time.hour += 12;
123                 }
124         }
125 //      cur_time.day_of_week = regs[6] & 7;
126         cur_time.day = regs[7] + (regs[8] & 3) * 10;
127         cur_time.day += start_day;
128         cur_time.month = regs[9] + (regs[10] & 1) * 10;
129         cur_time.year = regs[11] + regs[12] * 10;
130         cur_time.year += start_year;
131         cur_time.update_year();
132         cur_time.update_day_of_week();
133         
134         // restart event
135         cancel_event(this, register_id);
136 //#ifdef HAS_MSM5832
137 //      register_event(this, EVENT_INC, 1000000.0, true, &register_id);
138 //#else
139 //      register_event(this, EVENT_BUSY, 1000000.0, true, &register_id);
140 //#endif
141 }
142
143 void MSM58321_BASE::write_signal(int id, uint32_t data, uint32_t mask)
144 {
145         if(id == SIG_MSM58321_DATA) {
146                 wreg = (data & mask) | (wreg & ~mask);
147         } else if(id == SIG_MSM58321_CS) {
148                 bool next = ((data & mask) != 0);
149 //              if(!cs && next) {
150 //                      if(wr) {
151 //                              regs[regnum] = wreg & 0x0f;
152 //                              if(regnum <= 12) {
153 //                                      write_to_cur_time();
154 //                              }
155 //                      }
156 //                      if(addr_wr) {
157 //                              regnum = wreg & 0x0f;
158 //                      }
159 //              }
160                 cs = next;
161                 output_data();
162         } else if(id == SIG_MSM58321_READ) {
163                 rd = ((data & mask) != 0);
164                 output_data();
165         } else if(id == SIG_MSM58321_WRITE) {
166                 bool next = ((data & mask) != 0);
167                 if(!wr && next && cs) {
168                         regs[regnum] = wreg & 0x0f;
169                         if(regnum <= 12) {
170                                 write_to_cur_time();
171                         }
172                 }
173                 wr = next;
174         } else if(id == SIG_MSM58321_ADDR_WRITE) {
175                 bool next = ((data & mask) != 0);
176                 if(addr_wr && !next && cs) {
177                         regnum = wreg & 0x0f;
178                         output_data();
179                 }
180                 addr_wr = next;
181         } else if(id == SIG_MSM5832_ADDR) {
182                 regnum = (data & mask) | (regnum & ~mask);
183                 output_data();
184         } else if(id == SIG_MSM5832_HOLD) {
185                 hold = ((data & mask) != 0);
186         }
187 }
188
189 uint32_t MSM58321_BASE::read_signal(int ch)
190 {
191         if(ch == SIG_MSM58321_DATA) {
192                 return regs[regnum];
193         }
194         return 0;
195 }
196
197
198 void MSM58321_BASE::output_data()
199 {
200         if(cs && rd) {
201                 write_signals(&outputs_data, regs[regnum]);
202         }
203 }
204
205 void MSM58321_BASE::set_busy(bool val)
206 {
207 //#ifndef HAS_MSM5832
208 //      if(busy != val) {
209 //              write_signals(&outputs_busy, busy ? 0 : 0xffffffff);    // negative
210 //      }
211 //#endif
212         busy = val;
213 }
214
215 #define STATE_VERSION   1
216
217 bool MSM58321_BASE::process_state(FILEIO* state_fio, bool loading)
218 {
219         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
220                 return false;
221         }
222         if(!state_fio->StateCheckInt32(this_device_id)) {
223                 return false;
224         }
225         if(!cur_time.process_state((void *)state_fio, loading)) {
226                 return false;
227         }
228         state_fio->StateValue(register_id);
229         state_fio->StateArray(regs, sizeof(regs), 1);
230         state_fio->StateValue(wreg);
231         state_fio->StateValue(regnum);
232         state_fio->StateValue(cs);
233         state_fio->StateValue(rd);
234         state_fio->StateValue(wr);
235         state_fio->StateValue(addr_wr);
236         state_fio->StateValue(busy);
237         state_fio->StateValue(hold);
238         state_fio->StateValue(count_1024hz);
239         state_fio->StateValue(count_1s);
240         state_fio->StateValue(count_1m);
241         state_fio->StateValue(count_1h);
242         return true;
243  }