mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
Improvements to I/O emulation in new MC68705 device (nw)
- All internal memory handlers are now private members - DDRs zeroed when device reset (as per datasheet) - Port writes no longer transmit bits not set in DDR - DDR updates may cause port bits to be written out (this is important) - Add external read/write handlers for ports
This commit is contained in:
parent
67bded8842
commit
d9e1502ee0
@ -415,7 +415,7 @@ m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *
|
||||
{
|
||||
}
|
||||
|
||||
m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
|
||||
m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source)
|
||||
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||
m_program_config("program", ENDIANNESS_BIG, 8, addr_width, 0, internal_map)
|
||||
{
|
||||
@ -965,63 +965,146 @@ void m68705_device::execute_set_input(int inputnum, int state)
|
||||
|
||||
/* ddr - direction registers */
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_ddrA_w)
|
||||
WRITE8_MEMBER(m68705_new_device::internal_ddrA_w)
|
||||
{
|
||||
const u8 ddr_old = m_ddrA;
|
||||
m_ddrA = data;
|
||||
|
||||
// update outputs if lines switched to output
|
||||
if ((m_ddrA & ~ddr_old) != 0)
|
||||
update_portA_state();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_ddrB_w)
|
||||
WRITE8_MEMBER(m68705_new_device::internal_ddrB_w)
|
||||
{
|
||||
const u8 ddr_old = m_ddrB;
|
||||
m_ddrB = data;
|
||||
|
||||
// update outputs if lines switched to output
|
||||
if ((m_ddrB & ~ddr_old) != 0)
|
||||
update_portB_state();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_ddrC_w)
|
||||
WRITE8_MEMBER(m68705_new_device::internal_ddrC_w)
|
||||
{
|
||||
const u8 ddr_old = m_ddrC;
|
||||
m_ddrC = data;
|
||||
|
||||
// update outputs if lines switched to output
|
||||
if ((m_ddrC & ~ddr_old) != 0)
|
||||
update_portC_state();
|
||||
}
|
||||
|
||||
/* read ports */
|
||||
|
||||
READ8_MEMBER(m68705_new_device::mc68705_portA_r)
|
||||
READ8_MEMBER(m68705_new_device::internal_portA_r)
|
||||
{
|
||||
m_portA_in = m_portA_cb_r(0, ~m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pulled
|
||||
uint8_t res = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::mc68705_portB_r)
|
||||
{
|
||||
m_portB_in = m_portB_cb_r(0, ~m_ddrB);
|
||||
uint8_t res = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
|
||||
if (!m_portA_cb_r.isnull())
|
||||
m_portA_in = m_portA_cb_r(space, 0, ~m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pulled
|
||||
u8 res = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
|
||||
return res;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::mc68705_portC_r)
|
||||
READ8_MEMBER(m68705_new_device::internal_portB_r)
|
||||
{
|
||||
m_portC_in = m_portC_cb_r(0, ~m_ddrC);
|
||||
uint8_t res = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
|
||||
if (!m_portB_cb_r.isnull())
|
||||
m_portB_in = m_portB_cb_r(space, 0, ~m_ddrB);
|
||||
u8 res = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
|
||||
return res;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::internal_portC_r)
|
||||
{
|
||||
if (!m_portC_cb_r.isnull())
|
||||
m_portC_in = m_portC_cb_r(space, 0, ~m_ddrC);
|
||||
u8 res = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* write ports */
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_portA_w)
|
||||
WRITE8_MEMBER(m68705_new_device::internal_portA_w)
|
||||
{
|
||||
m_portA_cb_w(0, data, m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pushed
|
||||
// load the output latch
|
||||
m_portA_out = data;
|
||||
|
||||
// update the output lines
|
||||
update_portA_state();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_portB_w)
|
||||
void m68705_new_device::update_portA_state()
|
||||
{
|
||||
m_portB_cb_w(0, data, m_ddrB);
|
||||
// pass bits through DDR output mask
|
||||
m_portA_in = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
|
||||
|
||||
// pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
|
||||
m_portA_cb_w(space(AS_PROGRAM), 0, m_portA_in, m_ddrA);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::internal_portB_w)
|
||||
{
|
||||
// load the output latch
|
||||
m_portB_out = data;
|
||||
|
||||
// update the output lines
|
||||
update_portB_state();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::mc68705_portC_w)
|
||||
void m68705_new_device::update_portB_state()
|
||||
{
|
||||
m_portC_cb_w(0, data, m_ddrC);
|
||||
// pass bits through DDR output mask
|
||||
m_portB_in = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
|
||||
|
||||
// pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
|
||||
m_portB_cb_w(space(AS_PROGRAM), 0, m_portB_in, m_ddrB);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::internal_portC_w)
|
||||
{
|
||||
// load the output latch
|
||||
m_portC_out = data;
|
||||
|
||||
// update the output lines
|
||||
update_portC_state();
|
||||
}
|
||||
|
||||
void m68705_new_device::update_portC_state()
|
||||
{
|
||||
// pass bits through DDR output mask
|
||||
m_portC_in = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
|
||||
|
||||
// pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
|
||||
m_portC_cb_w(space(AS_PROGRAM), 0, m_portC_in, m_ddrC);
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::pa_r)
|
||||
{
|
||||
return m_portA_in;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::pb_r)
|
||||
{
|
||||
return m_portB_in;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m68705_new_device::pc_r)
|
||||
{
|
||||
return m_portC_in;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::pa_w)
|
||||
{
|
||||
COMBINE_DATA(&m_portA_in);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::pb_w)
|
||||
{
|
||||
COMBINE_DATA(&m_portB_in);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m68705_new_device::pc_w)
|
||||
{
|
||||
COMBINE_DATA(&m_portC_in);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1079,13 +1162,13 @@ selftest rom at similar area; selftest roms differ between the U2 and U3 version
|
||||
|
||||
*/
|
||||
|
||||
ADDRESS_MAP_START( m68705_internal_map, AS_PROGRAM, 8, m68705_new_device )
|
||||
AM_RANGE(0x000, 0x000) AM_READWRITE(mc68705_portA_r, mc68705_portA_w)
|
||||
AM_RANGE(0x001, 0x001) AM_READWRITE(mc68705_portB_r, mc68705_portB_w)
|
||||
AM_RANGE(0x002, 0x002) AM_READWRITE(mc68705_portC_r, mc68705_portC_w)
|
||||
AM_RANGE(0x004, 0x004) AM_WRITE(mc68705_ddrA_w)
|
||||
AM_RANGE(0x005, 0x005) AM_WRITE(mc68705_ddrB_w)
|
||||
AM_RANGE(0x006, 0x006) AM_WRITE(mc68705_ddrC_w)
|
||||
DEVICE_ADDRESS_MAP_START( internal_map, 8, m68705_new_device )
|
||||
AM_RANGE(0x000, 0x000) AM_READWRITE(internal_portA_r, internal_portA_w)
|
||||
AM_RANGE(0x001, 0x001) AM_READWRITE(internal_portB_r, internal_portB_w)
|
||||
AM_RANGE(0x002, 0x002) AM_READWRITE(internal_portC_r, internal_portC_w)
|
||||
AM_RANGE(0x004, 0x004) AM_WRITE(internal_ddrA_w)
|
||||
AM_RANGE(0x005, 0x005) AM_WRITE(internal_ddrB_w)
|
||||
AM_RANGE(0x006, 0x006) AM_WRITE(internal_ddrC_w)
|
||||
|
||||
AM_RANGE(0x010, 0x07f) AM_RAM
|
||||
AM_RANGE(0x080, 0x7ff) AM_ROM
|
||||
@ -1111,10 +1194,23 @@ void m68705_new_device::device_start()
|
||||
m_portB_cb_w.resolve_safe();
|
||||
m_portC_cb_w.resolve_safe();
|
||||
|
||||
m_portA_cb_r.resolve_safe(0xff);
|
||||
m_portB_cb_r.resolve_safe(0xff);
|
||||
m_portC_cb_r.resolve_safe(0xff);
|
||||
m_portA_cb_r.resolve();
|
||||
m_portB_cb_r.resolve();
|
||||
m_portC_cb_r.resolve();
|
||||
|
||||
m_portA_in = 0xff;
|
||||
m_portB_in = 0xff;
|
||||
m_portC_in = 0xff;
|
||||
}
|
||||
|
||||
void m68705_new_device::device_reset()
|
||||
{
|
||||
m68705_device::device_reset();
|
||||
|
||||
// all bits of ports A, B and C revert to inputs on reset
|
||||
m_ddrA = 0;
|
||||
m_ddrB = 0;
|
||||
m_ddrC = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -28,7 +28,7 @@ class m6805_base_device : public cpu_device
|
||||
public:
|
||||
// construction/destruction
|
||||
m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, const char *shortname, const char *source);
|
||||
m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source);
|
||||
m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
@ -330,7 +330,7 @@ public:
|
||||
m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: m6805_base_device(mconfig, tag, owner, clock, M68705, "M68705", 12, "m68705", __FILE__) { }
|
||||
|
||||
m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
|
||||
m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source)
|
||||
: m6805_base_device(mconfig, tag, owner, clock, type, name, addr_width, internal_map, shortname, source) { }
|
||||
|
||||
|
||||
@ -345,26 +345,24 @@ protected:
|
||||
|
||||
// ======================> m68705_new_device
|
||||
|
||||
ADDRESS_MAP_EXTERN(m68705_internal_map, 8);
|
||||
|
||||
|
||||
#define MCFG_M68705_PORTA_W_CB(_devcb) \
|
||||
m68705_new_device::set_portA_cb_w(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portA_cb_w(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_M68705_PORTB_W_CB(_devcb) \
|
||||
m68705_new_device::set_portB_cb_w(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portB_cb_w(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_M68705_PORTC_W_CB(_devcb) \
|
||||
m68705_new_device::set_portC_cb_w(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portC_cb_w(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_M68705_PORTA_R_CB(_devcb) \
|
||||
m68705_new_device::set_portA_cb_r(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portA_cb_r(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_M68705_PORTB_R_CB(_devcb) \
|
||||
m68705_new_device::set_portB_cb_r(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portB_cb_r(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_M68705_PORTC_R_CB(_devcb) \
|
||||
m68705_new_device::set_portC_cb_r(*device, DEVCB_##_devcb);
|
||||
devcb = &m68705_new_device::set_portC_cb_r(*device, DEVCB_##_devcb);
|
||||
|
||||
|
||||
class m68705_new_device : public m68705_device
|
||||
@ -372,7 +370,7 @@ class m68705_new_device : public m68705_device
|
||||
public:
|
||||
// construction/destruction
|
||||
m68705_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: m68705_device(mconfig, tag, owner, clock, M68705_NEW, "M68705 (NEW)", 11, ADDRESS_MAP_NAME( m68705_internal_map ), "m68705_new", __FILE__),
|
||||
: m68705_device(mconfig, tag, owner, clock, M68705_NEW, "M68705 (NEW)", 11, address_map_delegate(FUNC(m68705_new_device::internal_map), this), "m68705_new", __FILE__),
|
||||
m_portA_in(0),
|
||||
m_portB_in(0),
|
||||
m_portC_in(0),
|
||||
@ -399,31 +397,44 @@ public:
|
||||
template<class _Object> static devcb_base &set_portB_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portB_cb_r.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_portC_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portC_cb_r.set_callback(object); }
|
||||
|
||||
DECLARE_READ8_MEMBER(mc68705_portA_r);
|
||||
DECLARE_READ8_MEMBER(mc68705_portB_r);
|
||||
DECLARE_READ8_MEMBER(mc68705_portC_r);
|
||||
DECLARE_READ8_MEMBER(pa_r);
|
||||
DECLARE_READ8_MEMBER(pb_r);
|
||||
DECLARE_READ8_MEMBER(pc_r);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(mc68705_portA_w);
|
||||
DECLARE_WRITE8_MEMBER(mc68705_portB_w);
|
||||
DECLARE_WRITE8_MEMBER(mc68705_portC_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(mc68705_ddrA_w);
|
||||
DECLARE_WRITE8_MEMBER(mc68705_ddrB_w);
|
||||
DECLARE_WRITE8_MEMBER(mc68705_ddrC_w);
|
||||
DECLARE_WRITE8_MEMBER(pa_w);
|
||||
DECLARE_WRITE8_MEMBER(pb_w);
|
||||
DECLARE_WRITE8_MEMBER(pc_w);
|
||||
|
||||
protected:
|
||||
DECLARE_ADDRESS_MAP(internal_map, 8);
|
||||
|
||||
uint8_t m_portA_in;
|
||||
uint8_t m_portB_in;
|
||||
uint8_t m_portC_in;
|
||||
DECLARE_READ8_MEMBER(internal_portA_r);
|
||||
DECLARE_READ8_MEMBER(internal_portB_r);
|
||||
DECLARE_READ8_MEMBER(internal_portC_r);
|
||||
|
||||
uint8_t m_portA_out;
|
||||
uint8_t m_portB_out;
|
||||
uint8_t m_portC_out;
|
||||
DECLARE_WRITE8_MEMBER(internal_portA_w);
|
||||
DECLARE_WRITE8_MEMBER(internal_portB_w);
|
||||
DECLARE_WRITE8_MEMBER(internal_portC_w);
|
||||
|
||||
uint8_t m_ddrA;
|
||||
uint8_t m_ddrB;
|
||||
uint8_t m_ddrC;
|
||||
DECLARE_WRITE8_MEMBER(internal_ddrA_w);
|
||||
DECLARE_WRITE8_MEMBER(internal_ddrB_w);
|
||||
DECLARE_WRITE8_MEMBER(internal_ddrC_w);
|
||||
|
||||
void update_portA_state();
|
||||
void update_portB_state();
|
||||
void update_portC_state();
|
||||
|
||||
u8 m_portA_in;
|
||||
u8 m_portB_in;
|
||||
u8 m_portC_in;
|
||||
|
||||
u8 m_portA_out;
|
||||
u8 m_portB_out;
|
||||
u8 m_portC_out;
|
||||
|
||||
u8 m_ddrA;
|
||||
u8 m_ddrB;
|
||||
u8 m_ddrC;
|
||||
|
||||
/* Callbacks */
|
||||
devcb_write8 m_portA_cb_w;
|
||||
@ -437,6 +448,7 @@ protected:
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// virtual void execute_set_input(int inputnum, int state) override;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user