Пример #1
0
void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	if (m_count_extra)
	{
		m_count_extra = false;
		return;
	}

	// count down by twos
	m_counter -= 2;

	if (m_counter == 1)
	{
		LOGMASKED(LOG_TIMER, "Timer count half finished\n");

		// reload the even half of the count
		m_counter = m_count_loaded & 0x3ffe;

		// square wave modes produce a low output in the second half of the counting period
		if ((get_timer_mode() & TIMER_MODE_TC_PULSE) == 0)
			timer_output(0);
	}
	else if (m_counter == 2)
	{
		if ((get_timer_mode() & TIMER_MODE_TC_PULSE) != 0)
		{
			// pulse low on TC being reached
			timer_output(0);
		}

		// set timer flag
		m_status |= STATUS_TIMER;
	}
	else if (m_counter == 0)
	{
		timer_output(1);

		if ((get_timer_mode() & TIMER_MODE_AUTO_RELOAD) == 0 || (m_command & COMMAND_TM_MASK) == COMMAND_TM_STOP_AFTER_TC)
		{
			// stop timer
			timer_stop_count();
			LOGMASKED(LOG_TIMER, "Timer stopped\n");
		}
		else
		{
			// automatically reload the counter
			timer_reload_count();
		}
	}
}
Пример #2
0
inline void i8155_device::timer_stop_count()
{
	// stop counting
	m_timer->enable(0);

	// clear timer output
	timer_output(1);
}
Пример #3
0
void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	// count down
	m_counter--;

	if (get_timer_mode() == TIMER_MODE_LOW)
	{
		// pulse on every count
		pulse_timer_output();
	}

	if (m_counter == 0)
	{
		if (LOG) logerror("8155 '%s' Timer Count Reached\n", tag());

		switch (m_command & COMMAND_TM_MASK)
		{
		case COMMAND_TM_STOP_AFTER_TC:
			// stop timer
			m_timer->enable(0);

			if (LOG) logerror("8155 '%s' Timer Stopped\n", tag());
			break;
		}

		switch (get_timer_mode())
		{
		case TIMER_MODE_SQUARE_WAVE:
			// toggle timer output
			m_to = !m_to;
			timer_output();
			break;

		case TIMER_MODE_SINGLE_PULSE:
			// single pulse upon TC being reached
			pulse_timer_output();

			// clear timer mode setting
			m_command &= ~COMMAND_TM_MASK;
			break;

		case TIMER_MODE_AUTOMATIC_RELOAD:
			// automatic reload, i.e. single pulse every time TC is reached
			pulse_timer_output();
			break;
		}

		// set timer flag
		m_status |= STATUS_TIMER;

		// reload timer counter
		m_counter = m_count_length & 0x3fff;
	}
}
Пример #4
0
void bitbanger_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch(id)
	{
		case TIMER_OUTPUT:
			timer_output();
			break;

		case TIMER_INPUT:
			timer_input();
			break;
	}
}
Пример #5
0
inline void i8155_device::timer_reload_count()
{
	m_count_loaded = m_count_length;

	// valid counts range from 2 to 3FFF
	if ((m_count_length & 0x3fff) < 2)
	{
		timer_stop_count();
		return;
	}

	// begin the odd half of the count, with one extra cycle if count is odd
	m_counter = (m_count_loaded & 0x3ffe) | 1;
	m_count_extra = BIT(m_count_loaded, 0);

	// set up our timer
	m_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
	timer_output(1);

	switch (get_timer_mode())
	{
	case 0:
		// puts out LOW during second half of count
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: LOW)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_AUTO_RELOAD:
		// square wave, i.e. the period of the square wave equals the count length programmed with automatic reload at terminal count
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Square wave)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_TC_PULSE:
		// single pulse upon TC being reached
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Single pulse)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_TC_PULSE | TIMER_MODE_AUTO_RELOAD:
		// automatic reload, i.e. single pulse every time TC is reached
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Automatic reload)\n", m_count_loaded & 0x3fff);
		break;
	}
}
Пример #6
0
void i8155_device::device_reset()
{
	// clear output registers
	m_output[PORT_A] = 0;
	m_output[PORT_B] = 0;
	m_output[PORT_C] = 0;

	// set ports to input mode
	register_w(REGISTER_COMMAND, m_command & ~(COMMAND_PA | COMMAND_PB | COMMAND_PC_MASK));

	// clear timer flag
	m_status &= ~STATUS_TIMER;

	// stop counting
	m_timer->enable(0);

	// clear timer output
	m_to = 1;
	timer_output();
}
Пример #7
0
inline void i8155_device::pulse_timer_output()
{
	m_to = 0; timer_output();
	m_to = 1; timer_output();
}
Пример #8
0
void i8155_device::register_w(int offset, UINT8 data)
{
	switch (offset & 0x07)
	{
	case REGISTER_COMMAND:
		m_command = data;

		if (LOG) logerror("8155 '%s' Port A Mode: %s\n", tag(), (data & COMMAND_PA) ? "output" : "input");
		if (LOG) logerror("8155 '%s' Port B Mode: %s\n", tag(), (data & COMMAND_PB) ? "output" : "input");

		if (LOG) logerror("8155 '%s' Port A Interrupt: %s\n", tag(), (data & COMMAND_IEA) ? "enabled" : "disabled");
		if (LOG) logerror("8155 '%s' Port B Interrupt: %s\n", tag(), (data & COMMAND_IEB) ? "enabled" : "disabled");

		switch (data & COMMAND_PC_MASK)
		{
		case COMMAND_PC_ALT_1:
			if (LOG) logerror("8155 '%s' Port C Mode: Alt 1\n", tag());
			break;

		case COMMAND_PC_ALT_2:
			if (LOG) logerror("8155 '%s' Port C Mode: Alt 2\n", tag());
			break;

		case COMMAND_PC_ALT_3:
			if (LOG) logerror("8155 '%s' Port C Mode: Alt 3\n", tag());
			break;

		case COMMAND_PC_ALT_4:
			if (LOG) logerror("8155 '%s' Port C Mode: Alt 4\n", tag());
			break;
		}

		switch (data & COMMAND_TM_MASK)
		{
		case COMMAND_TM_NOP:
			// do not affect counter operation
			break;

		case COMMAND_TM_STOP:
			// NOP if timer has not started, stop counting if the timer is running
			if (LOG) logerror("8155 '%s' Timer Command: Stop\n", tag());
			m_to = 1;
			timer_output();
			m_timer->enable(0);
			break;

		case COMMAND_TM_STOP_AFTER_TC:
			// stop immediately after present TC is reached (NOP if timer has not started)
			if (LOG) logerror("8155 '%s' Timer Command: Stop after TC\n", tag());
			break;

		case COMMAND_TM_START:
			if (LOG) logerror("8155 '%s' Timer Command: Start\n", tag());

			if (m_timer->enabled())
			{
				// if timer is running, start the new mode and CNT length immediately after present TC is reached
			}
			else
			{
				// load mode and CNT length and start immediately after loading (if timer is not running)
				m_counter = m_count_length & 0x3fff;
				m_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
			}
			break;
		}
		break;

	case REGISTER_PORT_A:
		write_port(PORT_A, data);
		break;

	case REGISTER_PORT_B:
		write_port(PORT_B, data);
		break;

	case REGISTER_PORT_C:
		write_port(PORT_C, data & 0x3f);
		break;

	case REGISTER_TIMER_LOW:
		m_count_length = (m_count_length & 0xff00) | data;
		if (LOG) logerror("8155 '%s' Count Length Low: %04x\n", tag(), m_count_length);
		break;

	case REGISTER_TIMER_HIGH:
		m_count_length = (data << 8) | (m_count_length & 0xff);
		if (LOG) logerror("8155 '%s' Count Length High: %04x\n", tag(), m_count_length);

		switch (data & TIMER_MODE_MASK)
		{
		case TIMER_MODE_LOW:
			// puts out LOW during second half of count
			if (LOG) logerror("8155 '%s' Timer Mode: LOW\n", tag());
			break;

		case TIMER_MODE_SQUARE_WAVE:
			// square wave, i.e. the period of the square wave equals the count length programmed with automatic reload at terminal count
			if (LOG) logerror("8155 '%s' Timer Mode: Square wave\n", tag());
			break;

		case TIMER_MODE_SINGLE_PULSE:
			// single pulse upon TC being reached
			if (LOG) logerror("8155 '%s' Timer Mode: Single pulse\n", tag());
			break;

		case TIMER_MODE_AUTOMATIC_RELOAD:
			// automatic reload, i.e. single pulse every time TC is reached
			if (LOG) logerror("8155 '%s' Timer Mode: Automatic reload\n", tag());
			break;
		}
		break;
	}
}