diff options
Diffstat (limited to 'src/mess/drivers/cnsector.c')
-rw-r--r-- | src/mess/drivers/cnsector.c | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/src/mess/drivers/cnsector.c b/src/mess/drivers/cnsector.c index c78f19d074d..8aae3e34520 100644 --- a/src/mess/drivers/cnsector.c +++ b/src/mess/drivers/cnsector.c @@ -32,10 +32,17 @@ public: UINT16 m_o; + UINT16 m_leds_state[0x10]; + UINT16 m_leds_cache[0x10]; + UINT8 m_leds_decay[0x100]; + DECLARE_READ8_MEMBER(read_k); DECLARE_WRITE16_MEMBER(write_o); DECLARE_WRITE16_MEMBER(write_r); + TIMER_DEVICE_CALLBACK_MEMBER(leds_decay_tick); + void leds_update(); + virtual void machine_start(); }; @@ -43,6 +50,60 @@ public: /*************************************************************************** + LEDs + +***************************************************************************/ + +// Devices with TMS09x0 strobe the outputs very fast, it is unnoticeable to the user. +// To prevent flickering here, we need to simulate a decay. + +// decay time, in steps of 10ms +#define LEDS_DECAY_TIME 4 + +void cnsector_state::leds_update() +{ + UINT16 active_state[0x10]; + + for (int i = 0; i < 0x10; i++) + { + active_state[i] = 0; + + for (int j = 0; j < 0x10; j++) + { + int di = j << 4 | i; + + // turn on powered leds + if (m_leds_state[i] >> j & 1) + m_leds_decay[di] = LEDS_DECAY_TIME; + + // determine active state + int ds = (m_leds_decay[di] != 0) ? 1 : 0; + active_state[i] |= (ds << j); + } + } + + // on difference, send to output + for (int i = 0; i < 0x10; i++) + if (m_leds_cache[i] != active_state[i]) + output_set_digit_value(i, active_state[i]); + + memcpy(m_leds_cache, active_state, sizeof(m_leds_cache)); +} + +TIMER_DEVICE_CALLBACK_MEMBER(cnsector_state::leds_decay_tick) +{ + // slowly turn off unpowered leds + for (int i = 0; i < 0x100; i++) + if (!(m_leds_state[i & 0xf] >> (i>>4) & 1) && m_leds_decay[i]) + m_leds_decay[i]--; + + leds_update(); +} + + + +/*************************************************************************** + I/O ***************************************************************************/ @@ -61,9 +122,10 @@ READ8_MEMBER(cnsector_state::read_k) WRITE16_MEMBER(cnsector_state::write_r) { - // R0-R5: select digit + // R0-R5: select digit (right-to-left) for (int i = 0; i < 6; i++) - output_set_digit_value(i, (data >> i & 1) ? m_o : 0); + m_leds_state[i] = (data >> i & 1) ? m_o : 0; + leds_update(); // R6-R9: direction leds for (int i = 6; i < 10; i++) @@ -127,6 +189,9 @@ INPUT_PORTS_END void cnsector_state::machine_start() { + memset(m_leds_state, 0, sizeof(m_leds_state)); + memset(m_leds_cache, 0, sizeof(m_leds_cache)); + memset(m_leds_decay, 0, sizeof(m_leds_decay)); m_o = 0; save_item(NAME(m_o)); @@ -141,6 +206,8 @@ static MACHINE_CONFIG_START( cnsector, cnsector_state ) MCFG_TMS1XXX_WRITE_O_CB(WRITE16(cnsector_state, write_o)) MCFG_TMS1XXX_WRITE_R_CB(WRITE16(cnsector_state, write_r)) + MCFG_TIMER_DRIVER_ADD_PERIODIC("leds_decay", cnsector_state, leds_decay_tick, attotime::from_msec(10)) + MCFG_DEFAULT_LAYOUT(layout_cnsector) /* no video! */ |