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; } }
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(); } } }
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; } }