diff options
Diffstat (limited to 'src/devices/machine/upd4701.cpp')
-rw-r--r-- | src/devices/machine/upd4701.cpp | 305 |
1 files changed, 193 insertions, 112 deletions
diff --git a/src/devices/machine/upd4701.cpp b/src/devices/machine/upd4701.cpp index 8b6c161efbf..cfce7086b99 100644 --- a/src/devices/machine/upd4701.cpp +++ b/src/devices/machine/upd4701.cpp @@ -1,27 +1,38 @@ -// license:BSD-3-Clause +// license:BSD-3-Clause,AJR // copyright-holders:smf /*************************************************************************** - NEC uPD4701 - - Incremental Encoder Control - - 2009-06 Converted to be a device + NEC µPD4701A 2-Axis Incremental Encoder Counter ***************************************************************************/ #include "emu.h" #include "upd4701.h" -#define MASK_SWITCHES ( 7 ) #define MASK_COUNTER ( 0xfff ) -DEFINE_DEVICE_TYPE(UPD4701, upd4701_device, "upd4701", "uPD4701 Encoder") - -upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, UPD4701, tag, owner, clock) - , m_cs(0), m_xy(0), m_ul(0), m_resetx(0), m_resety(0), m_latchx(0), m_latchy(0) - , m_startx(0), m_starty(0), m_x(0), m_y(0), m_switches(0), m_latchswitches(0), m_cf(0) +DEFINE_DEVICE_TYPE(UPD4701A, upd4701_device, "upd4701a", "uPD4701A Incremental Encoder") + +upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, UPD4701A, tag, owner, clock) + , m_cs(true) + , m_xy(false) + , m_ul(false) + , m_resetx(false) + , m_resety(false) + , m_portx(*this, finder_base::DUMMY_TAG) + , m_porty(*this, finder_base::DUMMY_TAG) + , m_latchx(0) + , m_latchy(0) + , m_startx(0) + , m_starty(0) + , m_x(0) + , m_y(0) + , m_switches(0) + , m_latchswitches(0) + , m_cf(true) + , m_cf_cb(*this) + , m_sf_cb(*this) { } @@ -31,6 +42,11 @@ upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, d void upd4701_device::device_start() { + // resolve callbacks + m_cf_cb.resolve_safe(); + m_sf_cb.resolve_safe(); + + // register state for saving save_item(NAME(m_cs)); save_item(NAME(m_xy)); save_item(NAME(m_ul)); @@ -45,56 +61,35 @@ void upd4701_device::device_start() save_item(NAME(m_switches)); save_item(NAME(m_latchswitches)); save_item(NAME(m_cf)); + + // register special callback for analog inputs + if (m_portx.found() || m_porty.found()) + machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&upd4701_device::analog_update, this)); } //------------------------------------------------- -// device_reset - device-specific reset +// ul_w - write to counter select line //------------------------------------------------- -void upd4701_device::device_reset() -{ - m_cs = 1; - m_xy = 0; - m_ul = 0; - m_resetx = 0; - m_resety = 0; - m_latchx = 0; - m_latchy = 0; - m_startx = 0; - m_starty = 0; - m_x = 0; - m_y = 0; - m_switches = 0; - m_latchswitches = 0; - m_cf = 1; -} - -/* x,y increments can be 12bit (see MASK_COUNTER), hence we need a couple of -16bit handlers in the following */ - -/*------------------------------------------------- - ul_w --------------------------------------------------*/ - -WRITE_LINE_MEMBER( upd4701_device::ul_w ) +WRITE_LINE_MEMBER(upd4701_device::ul_w) { m_ul = state; } -/*------------------------------------------------- - xy_w --------------------------------------------------*/ +//------------------------------------------------- +// xy_w - write to byte select line +//------------------------------------------------- -WRITE_LINE_MEMBER( upd4701_device::xy_w ) +WRITE_LINE_MEMBER(upd4701_device::xy_w) { m_xy = state; } -/*------------------------------------------------- - cs_w --------------------------------------------------*/ +//------------------------------------------------- +// cs_w - write to chip select line +//------------------------------------------------- -WRITE_LINE_MEMBER( upd4701_device::cs_w ) +WRITE_LINE_MEMBER(upd4701_device::cs_w) { if (m_cs != state) { @@ -105,147 +100,233 @@ WRITE_LINE_MEMBER( upd4701_device::cs_w ) m_latchx = (m_x - m_startx) & MASK_COUNTER; m_latchy = (m_y - m_starty) & MASK_COUNTER; - m_latchswitches = (~m_switches) & MASK_SWITCHES; - if (m_latchswitches != 0) - { + m_latchswitches = m_switches; + if (m_switches != 0) m_latchswitches |= 8; - } - m_cf = 1; + if (!m_cf) + { + // CF remains inactive while CS is low + m_cf = true; + m_cf_cb(1); + } } } } -/*------------------------------------------------- - resetx_w --------------------------------------------------*/ +//------------------------------------------------- +// resetx_w - write to X counter reset line +//------------------------------------------------- -WRITE_LINE_MEMBER( upd4701_device::resetx_w ) +WRITE_LINE_MEMBER(upd4701_device::resetx_w) { if (m_resetx != state) { m_resetx = state; if (m_resetx) - { m_startx = m_x; - } } } -/*------------------------------------------------- - resety_w --------------------------------------------------*/ +//------------------------------------------------- +// resety_w - write to Y counter reset line +//------------------------------------------------- -WRITE_LINE_MEMBER( upd4701_device::resety_w ) +WRITE_LINE_MEMBER(upd4701_device::resety_w) { if (m_resety != state) { m_resety = state; if (m_resety) - { m_starty = m_y; - } } } -/*------------------------------------------------- - x_add --------------------------------------------------*/ +//------------------------------------------------- +// reset_xy - pulse the counter reset lines +//------------------------------------------------- + +WRITE8_MEMBER(upd4701_device::reset_xy) +{ + resetx_w(1); + resety_w(1); + resetx_w(0); + resety_w(0); +} + +//------------------------------------------------- +// analog_update - per-frame input update +//------------------------------------------------- + +void upd4701_device::analog_update() +{ + if (m_portx.found()) + x_add(m_portx->read() & MASK_COUNTER); + if (m_porty.found()) + y_add(m_porty->read() & MASK_COUNTER); +} + +//------------------------------------------------- +// x_add - count X-axis input +//------------------------------------------------- -void upd4701_device::x_add( int16_t data ) +void upd4701_device::x_add(s16 data) { if (!m_resetx && data != 0) { m_x += data; - if (m_cs) + if (m_cs && m_cf) { - m_cf = 0; + m_cf = false; + m_cf_cb(0); } } } -/*------------------------------------------------- - y_add --------------------------------------------------*/ +//------------------------------------------------- +// y_add - count Y-axis input +//------------------------------------------------- -void upd4701_device::y_add( int16_t data ) +void upd4701_device::y_add(s16 data) { if (!m_resety && data != 0) { m_y += data; - if (m_cs) + if (m_cs && m_cf) { - m_cf = 0; + m_cf = false; + m_cf_cb(0); } } } -/*------------------------------------------------- - switches_set --------------------------------------------------*/ +//------------------------------------------------- +// switch_update - update one of three switches +//------------------------------------------------- -void upd4701_device::switches_set( uint8_t data ) +void upd4701_device::switch_update(u8 mask, bool state) { - m_switches = data; + if (!state && (m_switches & mask) == 0) + { + // active low + m_switches |= mask; + + // update SF output if other switches were not active + if ((m_switches & ~mask) == 0) + m_sf_cb(0); + } + else if (state && (m_switches & mask) == mask) + { + // inactive high + m_switches &= ~mask; + + // update SF output if other switches are also inactive + if ((m_switches & ~mask) == 0) + m_sf_cb(1); + } } -/*------------------------------------------------- - d_r --------------------------------------------------*/ +//------------------------------------------------- +// left_w - update left switch state +//------------------------------------------------- -READ16_MEMBER( upd4701_device::d_r ) +WRITE_LINE_MEMBER(upd4701_device::left_w) { - int data; + switch_update(4, state); +} - if (m_cs) - { - return 0xff; - } +//------------------------------------------------- +// right_w - update right switch state +//------------------------------------------------- - if (m_xy) - { - data = m_latchy; - } - else +WRITE_LINE_MEMBER(upd4701_device::right_w) +{ + switch_update(2, state); +} + +//------------------------------------------------- +// middle_w - update middle switch state +//------------------------------------------------- + +WRITE_LINE_MEMBER(upd4701_device::middle_w) +{ + switch_update(1, state); +} + +//------------------------------------------------- +// d_r - read data lines directly +//------------------------------------------------- + +READ8_MEMBER(upd4701_device::d_r) +{ + if (m_cs) { - data = m_latchx; + logerror("Read while CS inactive\n"); + return space.unmap(); } + u16 data = m_xy ? m_latchy : m_latchx; data |= m_latchswitches << 12; if (m_ul) - { return data >> 8; - } else - { return data & 0xff; - } } -/*------------------------------------------------- - sf_r --------------------------------------------------*/ +//------------------------------------------------- +// read_x - read X axis through data/address bus +//------------------------------------------------- -READ_LINE_MEMBER( upd4701_device::sf_r ) +READ8_MEMBER(upd4701_device::read_x) { - if ((m_switches & MASK_SWITCHES) != MASK_SWITCHES) - { + return read_xy(space, (offset & 1) | 0); +} + +//------------------------------------------------- +// read_y - read Y axis through data/address bus +//------------------------------------------------- + +READ8_MEMBER(upd4701_device::read_y) +{ + return read_xy(space, (offset & 1) | 2); +} + +//------------------------------------------------- +// read_xy - read either axis through bus +//------------------------------------------------- + +READ8_MEMBER(upd4701_device::read_xy) +{ + cs_w(0); + xy_w(BIT(offset, 1)); + ul_w(BIT(offset, 0)); + u8 result = d_r(space, 0); + cs_w(1); + return result; +} + +//------------------------------------------------- +// sf_r - read switch flag +//------------------------------------------------- + +READ_LINE_MEMBER(upd4701_device::sf_r) +{ + if (m_switches != 0) return 0; - } return 1; } -/*------------------------------------------------- - cf_r --------------------------------------------------*/ +//------------------------------------------------- +// cf_r - read counter flag +//------------------------------------------------- -READ_LINE_MEMBER( upd4701_device::cf_r ) +READ_LINE_MEMBER(upd4701_device::cf_r) { return m_cf; } |