2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
16 #ifndef MSM58321_START_DAY
17 #define MSM58321_START_DAY 0
19 #ifndef MSM58321_START_YEAR
20 #define MSM58321_START_YEAR 0
23 void MSM58321::initialize()
26 memset(regs, 0, sizeof(regs));
31 rd = wr = addr_wr = busy = hold = false;
32 count_1024hz = count_1s = count_1m = count_1h = 0;
34 get_host_time(&cur_time);
39 register_event(this, EVENT_INC, 1000000.0, true, ®ister_id);
41 register_event(this, EVENT_BUSY, 1000000.0, true, ®ister_id);
43 register_event(this, EVENT_PULSE, 1000000.0 / 8192.0, true, NULL); // 122.1 usec
46 void MSM58321::event_callback(int event_id, int err)
48 if(event_id == EVENT_BUSY) {
50 register_event(this, EVENT_INC, 430, false, NULL);
51 } else if(event_id == EVENT_INC) {
52 if(cur_time.initialized) {
55 get_host_time(&cur_time); // resync
56 cur_time.initialized = true;
65 } else if(event_id == EVENT_PULSE) {
66 if(++count_1024hz == 4) {
70 if(++count_1s = 8192) {
76 if(++count_1m = 60 * 8192) {
82 if(++count_1h = 3600 * 8192) {
89 if(regnum == 14 || regnum == 15) {
95 void MSM58321::read_from_cur_time()
98 int hour = (regs[5] & 8) ? cur_time.hour : (cur_time.hour % 12);
99 int ampm = (cur_time.hour > 11) ? 4 : 0;
101 regs[ 0] = TO_BCD_LO(cur_time.second);
102 regs[ 1] = TO_BCD_HI(cur_time.second);
103 regs[ 2] = TO_BCD_LO(cur_time.minute);
104 regs[ 3] = TO_BCD_HI(cur_time.minute);
105 regs[ 4] = TO_BCD_LO(hour);
106 regs[ 5] = TO_BCD_HI(hour) | ampm | (regs[5] & 8);
107 regs[ 6] = cur_time.day_of_week;
108 regs[ 7] = TO_BCD_LO(cur_time.day - MSM58321_START_DAY);
109 regs[ 8] = TO_BCD_HI(cur_time.day - MSM58321_START_DAY) | (regs[8] & 0x0c);
110 regs[ 9] = TO_BCD_LO(cur_time.month);
111 regs[10] = TO_BCD_HI(cur_time.month);
112 regs[11] = TO_BCD_LO(cur_time.year - MSM58321_START_YEAR);
113 regs[12] = TO_BCD_HI(cur_time.year - MSM58321_START_YEAR);
116 void MSM58321::write_to_cur_time()
118 cur_time.second = regs[0] + (regs[1] & 7) * 10;
119 cur_time.minute = regs[2] + (regs[3] & 7) * 10;
120 cur_time.hour = regs[4] + (regs[5] & 3) * 10;
127 // cur_time.day_of_week = regs[6] & 7;
128 cur_time.day = regs[7] + (regs[8] & 3) * 10;
129 cur_time.day += MSM58321_START_DAY;
130 cur_time.month = regs[9] + (regs[10] & 1) * 10;
131 cur_time.year = regs[11] + regs[12] * 10;
132 cur_time.year += MSM58321_START_YEAR;
133 cur_time.update_year();
134 cur_time.update_day_of_week();
137 cancel_event(this, register_id);
139 register_event(this, EVENT_INC, 1000000.0, true, ®ister_id);
141 register_event(this, EVENT_BUSY, 1000000.0, true, ®ister_id);
145 void MSM58321::write_signal(int id, uint32_t data, uint32_t mask)
147 if(id == SIG_MSM58321_DATA) {
148 wreg = (data & mask) | (wreg & ~mask);
149 } else if(id == SIG_MSM58321_CS) {
150 bool next = ((data & mask) != 0);
153 // regs[regnum] = wreg & 0x0f;
154 // if(regnum <= 12) {
155 // write_to_cur_time();
159 // regnum = wreg & 0x0f;
164 } else if(id == SIG_MSM58321_READ) {
165 rd = ((data & mask) != 0);
167 } else if(id == SIG_MSM58321_WRITE) {
168 bool next = ((data & mask) != 0);
169 if(!wr && next && cs) {
170 regs[regnum] = wreg & 0x0f;
176 } else if(id == SIG_MSM58321_ADDR_WRITE) {
177 bool next = ((data & mask) != 0);
178 if(addr_wr && !next && cs) {
179 regnum = wreg & 0x0f;
183 } else if(id == SIG_MSM5832_ADDR) {
184 regnum = (data & mask) | (regnum & ~mask);
186 } else if(id == SIG_MSM5832_HOLD) {
187 hold = ((data & mask) != 0);
191 void MSM58321::output_data()
194 write_signals(&outputs_data, regs[regnum]);
198 void MSM58321::set_busy(bool val)
202 write_signals(&outputs_busy, busy ? 0 : 0xffffffff); // negative
208 #define STATE_VERSION 1
210 void MSM58321::save_state(FILEIO* state_fio)
212 state_fio->FputUint32(STATE_VERSION);
213 state_fio->FputInt32(this_device_id);
215 cur_time.save_state((void *)state_fio);
216 state_fio->FputInt32(register_id);
217 state_fio->Fwrite(regs, sizeof(regs), 1);
218 state_fio->FputUint8(wreg);
219 state_fio->FputUint8(regnum);
220 state_fio->FputBool(cs);
221 state_fio->FputBool(rd);
222 state_fio->FputBool(wr);
223 state_fio->FputBool(addr_wr);
224 state_fio->FputBool(busy);
225 state_fio->FputBool(hold);
226 state_fio->FputInt32(count_1024hz);
227 state_fio->FputInt32(count_1s);
228 state_fio->FputInt32(count_1m);
229 state_fio->FputInt32(count_1h);
232 bool MSM58321::load_state(FILEIO* state_fio)
234 if(state_fio->FgetUint32() != STATE_VERSION) {
237 if(state_fio->FgetInt32() != this_device_id) {
240 if(!cur_time.load_state((void *)state_fio)) {
243 register_id = state_fio->FgetInt32();
244 state_fio->Fread(regs, sizeof(regs), 1);
245 wreg = state_fio->FgetUint8();
246 regnum = state_fio->FgetUint8();
247 cs = state_fio->FgetBool();
248 rd = state_fio->FgetBool();
249 wr = state_fio->FgetBool();
250 addr_wr = state_fio->FgetBool();
251 busy = state_fio->FgetBool();
252 hold = state_fio->FgetBool();
253 count_1024hz = state_fio->FgetInt32();
254 count_1s = state_fio->FgetInt32();
255 count_1m = state_fio->FgetInt32();
256 count_1h = state_fio->FgetInt32();