2 FUJITSU FMR-30 Emulator 'eFMR-30'
\r
4 Author : Takeda.Toshiya
\r
11 #include "../i8259.h"
\r
12 #include "../../fileio.h"
\r
15 #define EVENT_32HZ 1
\r
16 #define EVENT_DONE 2
\r
27 void RTC::initialize()
\r
29 // load rtc regs image
\r
30 memset(regs, 0, sizeof(regs));
\r
31 regs[POWON] = 0x10; // cleared
\r
33 FILEIO* fio = new FILEIO();
\r
34 if(fio->Fopen(emu->bios_path(_T("RTC.BIN")), FILEIO_READ_BINARY)) {
\r
35 fio->Fread(regs + 8, 32, 1);
\r
41 // regs[POWON] &= 0x1f; // local power on
\r
42 // regs[POWOF] = 0x80; // program power off
\r
43 regs[POWON] = 0x10; // cleared
\r
44 regs[POWOF] = 0x20; // illegal power off
\r
51 emu->get_host_time(&cur_time);
\r
52 read_from_cur_time();
\r
55 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
\r
56 register_event_by_clock(this, EVENT_32HZ, CPU_CLOCKS >> 5, true, NULL);
\r
61 // set power off time
\r
62 regs[POFMI] = TO_BCD(cur_time.minute);
\r
63 regs[POFH] = TO_BCD(cur_time.hour);
\r
64 regs[POFD] = TO_BCD(cur_time.day);
\r
66 // save rtc regs image
\r
67 FILEIO* fio = new FILEIO();
\r
68 if(fio->Fopen(emu->bios_path(_T("RTC.BIN")), FILEIO_WRITE_BINARY)) {
\r
69 fio->Fwrite(regs + 8, 32, 1);
\r
75 void RTC::write_io16(uint32 addr, uint32 data)
\r
83 rtdsr &= ~(data & 0xe);
\r
91 register_event(this, EVENT_DONE, 100, false, NULL);
\r
100 uint32 RTC::read_io16(uint32 addr)
\r
111 void RTC::event_callback(int event_id, int err)
\r
113 if(event_id == EVENT_1HZ) {
\r
115 if(cur_time.initialized) {
\r
116 cur_time.increment();
\r
118 emu->get_host_time(&cur_time); // resync
\r
119 cur_time.initialized = true;
\r
121 read_from_cur_time();
\r
126 } else if(event_id == EVENT_32HZ) {
\r
129 } else if(event_id == EVENT_DONE) {
\r
130 int ch = (rtadr >> 1) & 0x3f;
\r
133 } else if(rtadr & 0x80) {
\r
136 regs[ch] = (uint8)rtobr;
\r
137 write_to_cur_time();
\r
138 } else if(ch == POWON) {
\r
139 regs[ch] = (regs[ch] & 0xe0) | (rtobr & 0x1f);
\r
140 if((rtobr & 0xe0) == 0xc0) {
\r
142 regs[ch] = (regs[ch] & 0x1f) | 0xc0;
\r
144 } else if((rtobr & 0xe0) == 0xe0) {
\r
149 } else if(7 <= ch && ch < 32) {
\r
150 regs[ch] = (uint8)rtobr;
\r
166 void RTC::read_from_cur_time()
\r
168 regs[0] = TO_BCD(cur_time.second);
\r
169 regs[1] = TO_BCD(cur_time.minute);
\r
170 regs[2] = TO_BCD(cur_time.hour);
\r
171 regs[3] = cur_time.day_of_week;
\r
172 regs[4] = TO_BCD(cur_time.day);
\r
173 regs[5] = TO_BCD(cur_time.month);
\r
174 regs[6] = TO_BCD(cur_time.year);
\r
177 void RTC::write_to_cur_time()
\r
179 cur_time.second = FROM_BCD(regs[0]);
\r
180 cur_time.minute = FROM_BCD(regs[1]);
\r
181 cur_time.hour = FROM_BCD(regs[2]);
\r
182 // cur_time.day_of_week = regs[3];
\r
183 cur_time.day = FROM_BCD(regs[4]);
\r
184 cur_time.month = FROM_BCD(regs[5]);
\r
185 cur_time.year = FROM_BCD(regs[6]);
\r
186 cur_time.update_year();
\r
187 cur_time.update_day_of_week();
\r
190 cancel_event(this, register_id);
\r
191 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
\r
194 void RTC::update_checksum()
\r
197 for(int i = 8; i < 32; i++) {
\r
198 sum += regs[i] & 0xf;
\r
199 sum += (regs[i] >> 4) & 0xf;
\r
201 uint8 ckh = (sum >> 6) & 0xf;
\r
202 uint8 ckm = (sum >> 2) & 0xf;
\r
203 uint8 ckl = (sum >> 0) & 3;
\r
205 regs[CKHM] = ckh | (ckm << 4);
\r
206 regs[CKL] = (regs[CKL] & 0xf0) | ckl | 0xc;
\r
209 void RTC::update_intr()
\r
211 d_pic->write_signal(SIG_I8259_CHIP0 | SIG_I8259_IR1, (rtcmr & rtdsr & 0xe) ? 1 : 0, 1);
\r