2 FUJITSU FMR-30 Emulator 'eFMR-30'
4 Author : Takeda.Toshiya
26 DLL_PREFIX_I struct cur_time_s cur_time;
29 void RTC::initialize()
31 // load rtc regs image
32 memset(regs, 0, sizeof(regs));
33 regs[POWON] = 0x10; // cleared
35 FILEIO* fio = new FILEIO();
36 if(fio->Fopen(create_local_path(_T("RTC.BIN")), FILEIO_READ_BINARY)) {
37 fio->Fread(regs + 8, 32, 1);
43 // regs[POWON] &= 0x1f; // local power on
44 // regs[POWOF] = 0x80; // program power off
45 regs[POWON] = 0x10; // cleared
46 regs[POWOF] = 0x20; // illegal power off
53 get_host_time(&cur_time);
57 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
58 register_event_by_clock(this, EVENT_32HZ, CPU_CLOCKS >> 5, true, NULL);
64 regs[POFMI] = TO_BCD(cur_time.minute);
65 regs[POFH] = TO_BCD(cur_time.hour);
66 regs[POFD] = TO_BCD(cur_time.day);
68 // save rtc regs image
69 FILEIO* fio = new FILEIO();
70 if(fio->Fopen(create_local_path(_T("RTC.BIN")), FILEIO_WRITE_BINARY)) {
71 fio->Fwrite(regs + 8, 32, 1);
77 void RTC::write_io16(uint32_t addr, uint32_t data)
85 rtdsr &= ~(data & 0xe);
93 register_event(this, EVENT_DONE, 100, false, NULL);
102 uint32_t RTC::read_io16(uint32_t addr)
113 void RTC::event_callback(int event_id, int err)
115 if(event_id == EVENT_1HZ) {
117 if(cur_time.initialized) {
118 cur_time.increment();
120 get_host_time(&cur_time); // resync
121 cur_time.initialized = true;
123 read_from_cur_time();
128 } else if(event_id == EVENT_32HZ) {
131 } else if(event_id == EVENT_DONE) {
132 int ch = (rtadr >> 1) & 0x3f;
135 } else if(rtadr & 0x80) {
138 regs[ch] = (uint8_t)rtobr;
140 } else if(ch == POWON) {
141 regs[ch] = (regs[ch] & 0xe0) | (rtobr & 0x1f);
142 if((rtobr & 0xe0) == 0xc0) {
144 regs[ch] = (regs[ch] & 0x1f) | 0xc0;
146 } else if((rtobr & 0xe0) == 0xe0) {
151 } else if(7 <= ch && ch < 32) {
152 regs[ch] = (uint8_t)rtobr;
168 void RTC::read_from_cur_time()
170 regs[0] = TO_BCD(cur_time.second);
171 regs[1] = TO_BCD(cur_time.minute);
172 regs[2] = TO_BCD(cur_time.hour);
173 regs[3] = cur_time.day_of_week;
174 regs[4] = TO_BCD(cur_time.day);
175 regs[5] = TO_BCD(cur_time.month);
176 regs[6] = TO_BCD(cur_time.year);
179 void RTC::write_to_cur_time()
181 cur_time.second = FROM_BCD(regs[0]);
182 cur_time.minute = FROM_BCD(regs[1]);
183 cur_time.hour = FROM_BCD(regs[2]);
184 // cur_time.day_of_week = regs[3];
185 cur_time.day = FROM_BCD(regs[4]);
186 cur_time.month = FROM_BCD(regs[5]);
187 cur_time.year = FROM_BCD(regs[6]);
188 cur_time.update_year();
189 cur_time.update_day_of_week();
192 cancel_event(this, register_id);
193 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
196 void RTC::update_checksum()
199 for(int i = 8; i < 32; i++) {
200 sum += regs[i] & 0xf;
201 sum += (regs[i] >> 4) & 0xf;
203 uint8_t ckh = (sum >> 6) & 0xf;
204 uint8_t ckm = (sum >> 2) & 0xf;
205 uint8_t ckl = (sum >> 0) & 3;
207 regs[CKHM] = ckh | (ckm << 4);
208 regs[CKL] = (regs[CKL] & 0xf0) | ckl | 0xc;
211 void RTC::update_intr()
213 d_pic->write_signal(SIG_I8259_CHIP0 | SIG_I8259_IR1, (rtcmr & rtdsr & 0xe) ? 1 : 0, 1);
216 #define STATE_VERSION 1
218 bool RTC::process_state(FILEIO* state_fio, bool loading)
220 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
223 if(!state_fio->StateCheckInt32(this_device_id)) {
226 if(!cur_time.process_state((void *)state_fio, loading)) {
229 state_fio->StateInt32(register_id);
230 state_fio->StateUint16(rtcmr);
231 state_fio->StateUint16(rtdsr);
232 state_fio->StateUint16(rtadr);
233 state_fio->StateUint16(rtobr);
234 state_fio->StateUint16(rtibr);
235 state_fio->StateBuffer(regs, sizeof(regs), 1);