Ejemplo n.º 1
0
void RTC::event_callback(int event_id, int err)
{
	if(event_id == EVENT_1HZ) {
		// update calendar
		if(cur_time.initialized) {
			cur_time.increment();
		} else {
			get_host_time(&cur_time);	// resync
			cur_time.initialized = true;
		}
		read_from_cur_time();
		
		// 1sec interrupt
		rtdsr |= 4;
		update_intr();
	} else if(event_id == EVENT_32HZ) {
		// update tcnt
		regs[TCNT]++;
	} else if(event_id == EVENT_DONE) {
		int ch = (rtadr >> 1) & 0x3f;
		if(rtadr & 1) {
			// invalid address
		} else if(rtadr & 0x80) {
			// write
			if(ch <= 6) {
				regs[ch] = (uint8_t)rtobr;
				write_to_cur_time();
			} else if(ch == POWON) {
				regs[ch] = (regs[ch] & 0xe0) | (rtobr & 0x1f);
				if((rtobr & 0xe0) == 0xc0) {
					// reipl
					regs[ch] = (regs[ch] & 0x1f) | 0xc0;
					vm->reset();
				} else if((rtobr & 0xe0) == 0xe0) {
					// power off
					emu->power_off();
				}
				update_checksum();
			} else if(7 <= ch && ch < 32) {
				regs[ch] = (uint8_t)rtobr;
				update_checksum();
			}
		} else {
			// read
			if(ch < 40) {
				rtibr = regs[ch];
			}
		}
		// update flags
		rtdsr &= ~1;
		rtdsr |= 2;
		update_intr();
	}
Ejemplo n.º 2
0
void RP5C01::write_io8(uint32 addr, uint32 data)
{
	addr &= 0x0f;
	if(addr <= 0x0c) {
#ifndef HAS_RP5C15
		switch(regs[0x0d] & 3) {
#else
		switch(regs[0x0d] & 1) {
#endif
		case 0:
			if(time[addr] != data) {
				time[addr] = data;
				write_to_cur_time();
			}
			return;
#ifndef HAS_RP5C15
		case 2:
			ram[addr] = data;
			return;
		case 3:
			ram[addr + 13] = data;
			return;
#endif
		}
	}
	
	uint8 tmp = regs[addr] ^ data;
	regs[addr] = data;
	
	if(addr == 0x0a) {
		if(tmp & 1) {
			// am/pm is changed
			read_from_cur_time();
		}
	} else if(addr == 0x0f) {
#ifndef HAS_RP5C15
		switch(regs[0x0d] & 3) {
#else
		switch(regs[0x0d] & 1) {
#endif
		case 0:
			if(data & 3) {
				// timer reset
			}
			break;
		case 1:
#ifndef HAS_RP5C15
		case 2:
		case 3:
#endif
			if(data & 2) {
				// timer reset
			}
			if(data & 1) {
				if(alarm) {
					alarm = false;
					update_pulse();
				}
			}
			break;
		}
	}
}

uint32 RP5C01::read_io8(uint32 addr)
{
	addr &= 0x0f;
	if(addr <= 0x0c) {
#ifndef HAS_RP5C15
		switch(regs[0x0d] & 3) {
#else
		switch(regs[0x0d] & 1) {
#endif
		case 0:
			return time[addr];
#ifndef HAS_RP5C15
		case 2:
			return ram[addr];
		case 3:
			return ram[addr + 13];
#endif
		}
	}
	if(addr == 0x0b) {
		for(int i = 0; i < 3; i++) {
			if(LEAP_YEAR(cur_time.year - i)) {
				return i;
			}
		}
		return 3;
	}
	return regs[addr];
}

void RP5C01::event_callback(int event_id, int err)
{
	if(event_id == EVENT_1SEC) {
		if(cur_time.initialized) {
			cur_time.increment();
		} else {
			emu->get_host_time(&cur_time);	// resync
			cur_time.initialized = true;
		}
		if(regs[0x0d] & 8) {
			read_from_cur_time();
			if(regs[0x0d] & 4) {
				update_pulse();
			}
		}
	} else if(event_id == EVENT_16HZ) {
		bool update = false;
		// 1Hz
		if(++count_16hz == 16) {
			pulse_1hz = !pulse_1hz;
			if(!(regs[0x0f] & 8)) {
				update = true;
			}
			count_16hz = 0;
		}
		// 16Hz
		pulse_16hz = !pulse_16hz;
		if(!(regs[0x0f] & 4)) {
			update = true;
		}
		if(update) {
			update_pulse();
		}
	}
	
	// update signal
}

void RP5C01::update_pulse()
{
	bool pulse = false;
	
	if(regs[0x0d] & 4) {
		pulse |= alarm;
	}
	if(!(regs[0x0f] & 8)) {
		pulse |= pulse_1hz;
	}
	if(!(regs[0x0f] & 4)) {
		pulse |= pulse_16hz;
	}
	write_signals(&outputs_pulse, pulse ? 0 : 0xffffffff);
}

#define MODE_12H !(regs[0x0a] & 1)

void RP5C01::read_from_cur_time()
{
	int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour;
	int ampm = (MODE_12H && cur_time.hour >= 12) ? 2 : 0;
	
	time[ 0] = TO_BCD_LO(cur_time.second);
	time[ 1] = TO_BCD_HI(cur_time.second);
	time[ 2] = TO_BCD_LO(cur_time.minute);
	time[ 3] = TO_BCD_HI(cur_time.minute);
	time[ 4] = TO_BCD_LO(hour);
	time[ 5] = TO_BCD_HI(hour) | ampm;
	time[ 6] = cur_time.day_of_week;
	time[ 7] = TO_BCD_LO(cur_time.day);
	time[ 8] = TO_BCD_HI(cur_time.day);
	time[ 9] = TO_BCD_LO(cur_time.month);
	time[10] = TO_BCD_HI(cur_time.month);
	time[11] = TO_BCD_LO(cur_time.year);
	time[12] = TO_BCD_HI(cur_time.year);
	
	// check alarm
	static uint8 mask[9] = {0, 0, 0x0f, 0x07, 0x0f, 0x03, 0x07, 0x0f, 0x03};
	bool tmp = true;
	
	for(int i = 3; i < 9; i++) {
		if((time[i] & mask[i]) != (regs[i] & mask[i])) {
			tmp = false;
			break;
		}
	}
	if(tmp) {
		alarm = true;
	}
}