// license:BSD-3-Clause
// copyright-holders:smf
/***************************************************************************
NEC uPD4701
Incremental Encoder Control
2009-06 Converted to be a device
***************************************************************************/
#include "emu.h"
#include "upd4701.h"
#define MASK_SWITCHES ( 7 )
#define MASK_COUNTER ( 0xfff )
const device_type UPD4701 = device_creator<upd4701_device>;
upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, UPD4701, "uPD4701 Encoder", tag, owner, clock, "upd4701", __FILE__), 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)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void upd4701_device::device_start()
{
save_item(NAME(m_cs));
save_item(NAME(m_xy));
save_item(NAME(m_ul));
save_item(NAME(m_resetx));
save_item(NAME(m_resety));
save_item(NAME(m_latchx));
save_item(NAME(m_latchy));
save_item(NAME(m_startx));
save_item(NAME(m_starty));
save_item(NAME(m_x));
save_item(NAME(m_y));
save_item(NAME(m_switches));
save_item(NAME(m_latchswitches));
save_item(NAME(m_cf));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
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 )
{
m_ul = state;
}
/*-------------------------------------------------
xy_w
-------------------------------------------------*/
WRITE_LINE_MEMBER( upd4701_device::xy_w )
{
m_xy = state;
}
/*-------------------------------------------------
cs_w
-------------------------------------------------*/
WRITE_LINE_MEMBER( upd4701_device::cs_w )
{
if (m_cs != state)
{
m_cs = state;
if (!m_cs)
{
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 |= 8;
}
m_cf = 1;
}
}
}
/*-------------------------------------------------
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
-------------------------------------------------*/
WRITE_LINE_MEMBER( upd4701_device::resety_w )
{
if (m_resety != state)
{
m_resety = state;
if (m_resety)
{
m_starty = m_y;
}
}
}
/*-------------------------------------------------
x_add
-------------------------------------------------*/
void upd4701_device::x_add( int16_t data )
{
if (!m_resetx && data != 0)
{
m_x += data;
if (m_cs)
{
m_cf = 0;
}
}
}
/*-------------------------------------------------
y_add
-------------------------------------------------*/
void upd4701_device::y_add( int16_t data )
{
if (!m_resety && data != 0)
{
m_y += data;
if (m_cs)
{
m_cf = 0;
}
}
}
/*-------------------------------------------------
switches_set
-------------------------------------------------*/
void upd4701_device::switches_set( uint8_t data )
{
m_switches = data;
}
/*-------------------------------------------------
d_r
-------------------------------------------------*/
READ16_MEMBER( upd4701_device::d_r )
{
int data;
if (m_cs)
{
return 0xff;
}
if (m_xy)
{
data = m_latchy;
}
else
{
data = m_latchx;
}
data |= m_latchswitches << 12;
if (m_ul)
{
return data >> 8;
}
else
{
return data & 0xff;
}
}
/*-------------------------------------------------
sf_r
-------------------------------------------------*/
READ_LINE_MEMBER( upd4701_device::sf_r )
{
if ((m_switches & MASK_SWITCHES) != MASK_SWITCHES)
{
return 0;
}
return 1;
}
/*-------------------------------------------------
cf_r
-------------------------------------------------*/
READ_LINE_MEMBER( upd4701_device::cf_r )
{
return m_cf;
}