mirror of
https://github.com/holub/mame
synced 2025-06-03 19:36:26 +03:00
192 lines
4.8 KiB
C
192 lines
4.8 KiB
C
/**********************************************************************
|
|
|
|
LH5810/LH5811 Input/Output Port Controller
|
|
|
|
TODO:
|
|
- serial data transfer
|
|
- data transfer to the cassette tape
|
|
|
|
**********************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "lh5810.h"
|
|
|
|
//**************************************************************************
|
|
// GLOBAL VARIABLES
|
|
//**************************************************************************
|
|
|
|
const device_type LH5810 = &device_creator<lh5810_device>;
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_config_complete - perform any
|
|
// operations now that the configuration is
|
|
// complete
|
|
//-------------------------------------------------
|
|
|
|
void lh5810_device::device_config_complete()
|
|
{
|
|
// inherit a copy of the static data
|
|
const lh5810_interface *intf = reinterpret_cast<const lh5810_interface *>(static_config());
|
|
if (intf != NULL)
|
|
*static_cast<lh5810_interface *>(this) = *intf;
|
|
|
|
// or initialize to defaults if none provided
|
|
else
|
|
{
|
|
memset(&m_porta_r_cb, 0, sizeof(m_porta_r_cb));
|
|
memset(&m_porta_w_cb, 0, sizeof(m_porta_w_cb));
|
|
memset(&m_portb_r_cb, 0, sizeof(m_portb_r_cb));
|
|
memset(&m_portb_w_cb, 0, sizeof(m_portb_w_cb));
|
|
memset(&m_portc_w_cb, 0, sizeof(m_portc_w_cb));
|
|
memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
|
|
}
|
|
}
|
|
|
|
|
|
//**************************************************************************
|
|
// LIVE DEVICE
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// lh5810_device - constructor
|
|
//-------------------------------------------------
|
|
|
|
lh5810_device::lh5810_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: device_t(mconfig, LH5810, "LH5810", tag, owner, clock)
|
|
{
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_start - device-specific startup
|
|
//-------------------------------------------------
|
|
|
|
void lh5810_device::device_start()
|
|
{
|
|
// resolve callbacks
|
|
m_porta_r_func.resolve(m_porta_r_cb, *this);
|
|
m_porta_w_func.resolve(m_porta_w_cb, *this);
|
|
m_portb_r_func.resolve(m_portb_r_cb, *this);
|
|
m_portb_w_func.resolve(m_portb_w_cb, *this);
|
|
m_portc_w_func.resolve(m_portc_w_cb, *this);
|
|
m_out_int_func.resolve(m_out_int_cb, *this);
|
|
|
|
// register for state saving
|
|
save_item(NAME(m_irq));
|
|
save_item(NAME(m_reg));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_reset - device-specific reset
|
|
//-------------------------------------------------
|
|
|
|
void lh5810_device::device_reset()
|
|
{
|
|
memset(m_reg, 0, sizeof(m_reg));
|
|
m_irq = 0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// data_r - data read
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( lh5810_device::data_r )
|
|
{
|
|
switch (offset)
|
|
{
|
|
case LH5810_U:
|
|
case LH5810_L:
|
|
case LH5810_G:
|
|
case LH5810_DDA:
|
|
case LH5810_DDB:
|
|
case LH5810_OPC:
|
|
case LH5820_F:
|
|
return m_reg[offset];
|
|
|
|
case LH5810_IF:
|
|
if (BIT(m_portb_r_func(0) & ~m_reg[LH5810_DDB], 7))
|
|
m_reg[offset] |= 2;
|
|
else
|
|
m_reg[offset] &= 0xfd;
|
|
|
|
return m_reg[offset];
|
|
|
|
case LH5810_MSK:
|
|
return (m_reg[offset]&0x0f) | (m_irq<<4) | (BIT(m_reg[LH5810_OPB],7)<<5);
|
|
|
|
case LH5810_OPA:
|
|
m_reg[offset] = (m_reg[offset] & m_reg[LH5810_DDA]) | (m_porta_r_func(0) & ~m_reg[LH5810_DDA]);
|
|
return m_reg[offset];
|
|
|
|
case LH5810_OPB:
|
|
m_reg[offset] = (m_reg[offset] & m_reg[LH5810_DDB]) | (m_portb_r_func(0) & ~m_reg[LH5810_DDB]);
|
|
m_out_int_func((m_reg[offset] & 0x80 && m_reg[LH5810_MSK] & 0x02) ? ASSERT_LINE : CLEAR_LINE);
|
|
return m_reg[offset];
|
|
|
|
default:
|
|
return 0x00;
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// data_w - data write
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( lh5810_device::data_w )
|
|
{
|
|
switch (offset)
|
|
{
|
|
case LH5810_RESET:
|
|
break;
|
|
|
|
case LH5810_G:
|
|
case LH5820_F:
|
|
case LH5810_DDA:
|
|
case LH5810_DDB:
|
|
m_reg[offset] = data;
|
|
break;
|
|
|
|
case LH5810_U:
|
|
//writing on U register clear the RD flag of IF register
|
|
m_reg[LH5810_IF] &= 0xfb;
|
|
m_reg[offset] = data;
|
|
break;
|
|
|
|
case LH5810_L:
|
|
//writing on L register clear the TD flag of IF register
|
|
m_reg[LH5810_IF] &= 0xf7;
|
|
m_reg[offset] = data;
|
|
break;
|
|
|
|
case LH5810_MSK:
|
|
m_reg[offset] = data & 0x0f;
|
|
break;
|
|
|
|
case LH5810_IF:
|
|
//only bit 0 and 1 are writable
|
|
m_reg[offset] = (m_reg[offset] & 0xfc) | (data & 0x03);
|
|
break;
|
|
|
|
case LH5810_OPA:
|
|
m_reg[offset] = (data & m_reg[LH5810_DDA]) | (m_reg[offset] & ~m_reg[LH5810_DDA]);
|
|
m_porta_w_func(0, m_reg[offset]);
|
|
break;
|
|
|
|
case LH5810_OPB:
|
|
m_reg[offset] = (data & m_reg[LH5810_DDB]) | (m_reg[offset] & ~m_reg[LH5810_DDB]);
|
|
m_portb_w_func(0, m_reg[offset]);
|
|
m_out_int_func((m_reg[offset] & 0x80 && m_reg[LH5810_MSK] & 0x02) ? ASSERT_LINE : CLEAR_LINE);
|
|
break;
|
|
|
|
case LH5810_OPC:
|
|
m_reg[offset] = data;
|
|
m_portc_w_func(0, m_reg[offset]);
|
|
break;
|
|
}
|
|
}
|
|
|