mirror of
https://github.com/holub/mame
synced 2025-05-28 08:33:05 +03:00
187 lines
4.3 KiB
C
187 lines
4.3 KiB
C
/**********************************************************************
|
|
|
|
General Instruments AY-5-3600 Keyboard Encoder emulation
|
|
|
|
Copyright MESS Team.
|
|
Visit http://mamedev.org for licensing and usage restrictions.
|
|
|
|
*********************************************************************/
|
|
|
|
/*
|
|
|
|
TODO:
|
|
|
|
- scan timer clock frequency
|
|
- more accurate emulation of real chip
|
|
|
|
*/
|
|
|
|
#include "kb3600.h"
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACROS / CONSTANTS
|
|
//**************************************************************************
|
|
|
|
#define LOG 0
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// GLOBAL VARIABLES
|
|
//**************************************************************************
|
|
|
|
// devices
|
|
const device_type AY3600 = &device_creator<ay3600_device>;
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// DEVICE CONFIGURATION
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// device_config_complete - perform any
|
|
// operations now that the configuration is
|
|
// complete
|
|
//-------------------------------------------------
|
|
|
|
void ay3600_device::device_config_complete()
|
|
{
|
|
// inherit a copy of the static data
|
|
const ay3600_interface *intf = reinterpret_cast<const ay3600_interface *>(static_config());
|
|
if (intf != NULL)
|
|
*static_cast<ay3600_interface *>(this) = *intf;
|
|
|
|
// or initialize to defaults if none provided
|
|
else
|
|
{
|
|
memset(&m_in_shift_cb, 0, sizeof(m_in_shift_cb));
|
|
memset(&m_in_control_cb, 0, sizeof(m_in_control_cb));
|
|
memset(&m_out_data_ready_cb, 0, sizeof(m_out_data_ready_cb));
|
|
memset(&m_out_ako_cb, 0, sizeof(m_out_ako_cb));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// LIVE DEVICE
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// ay3600_device - constructor
|
|
//-------------------------------------------------
|
|
|
|
ay3600_device::ay3600_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: device_t(mconfig, AY3600, "AY-5-3600", tag, owner, clock)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------
|
|
// device_start - device-specific startup
|
|
//-------------------------------------------------
|
|
|
|
void ay3600_device::device_start()
|
|
{
|
|
// resolve callbacks
|
|
m_in_x_func[0].resolve(m_in_x0_cb, *this);
|
|
m_in_x_func[1].resolve(m_in_x1_cb, *this);
|
|
m_in_x_func[2].resolve(m_in_x2_cb, *this);
|
|
m_in_x_func[3].resolve(m_in_x3_cb, *this);
|
|
m_in_x_func[4].resolve(m_in_x4_cb, *this);
|
|
m_in_x_func[5].resolve(m_in_x5_cb, *this);
|
|
m_in_x_func[6].resolve(m_in_x6_cb, *this);
|
|
m_in_x_func[7].resolve(m_in_x7_cb, *this);
|
|
m_in_x_func[8].resolve(m_in_x8_cb, *this);
|
|
m_in_shift_func.resolve(m_in_shift_cb, *this);
|
|
m_in_control_func.resolve(m_in_control_cb, *this);
|
|
m_out_data_ready_func.resolve(m_out_data_ready_cb, *this);
|
|
m_out_ako_func.resolve(m_out_ako_cb, *this);
|
|
|
|
// allocate timers
|
|
m_scan_timer = timer_alloc();
|
|
m_scan_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
|
|
|
|
// state saving
|
|
save_item(NAME(m_b));
|
|
save_item(NAME(m_ako));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// device_start - device-specific reset
|
|
//-------------------------------------------------
|
|
|
|
void ay3600_device::device_reset()
|
|
{
|
|
m_ako = 0;
|
|
}
|
|
|
|
//-------------------------------------------------
|
|
// device_timer - handler timer events
|
|
//-------------------------------------------------
|
|
|
|
void ay3600_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
|
{
|
|
int ako = 0;
|
|
|
|
for (int x = 0; x < 9; x++)
|
|
{
|
|
UINT16 data = m_in_x_func[x](0,0xffff);
|
|
|
|
for (int y = 0; y < 10; y++)
|
|
{
|
|
if (BIT(data, y))
|
|
{
|
|
int b = (x * 10) + y;
|
|
|
|
ako = 1;
|
|
|
|
if (b > 63)
|
|
{
|
|
b -= 64;
|
|
b = 0x100 | b;
|
|
}
|
|
|
|
b |= (m_in_shift_func() << 6);
|
|
b |= (m_in_control_func() << 7);
|
|
|
|
if (m_b != b)
|
|
{
|
|
m_b = b;
|
|
|
|
m_out_data_ready_func(1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!ako)
|
|
{
|
|
m_b = -1;
|
|
}
|
|
|
|
if (ako != m_ako)
|
|
{
|
|
m_out_ako_func(ako);
|
|
m_ako = ako;
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// b_r -
|
|
//-------------------------------------------------
|
|
|
|
UINT16 ay3600_device::b_r()
|
|
{
|
|
UINT16 data = m_b;
|
|
|
|
m_out_data_ready_func(0);
|
|
|
|
return data;
|
|
}
|