summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/315_5338a.cpp
blob: 3dff245893375beb30523610fd2a7c11d7de07b0 (plain) (tree)


































                                                                                                                               


                                                                                       
 
                                                                          










                                                   





                                                   

                                   

                                            














                                                                            












                                                       
 

                                               


                                                 























                                                           








                                            

                                                    

                      
                                                          










                                                                                    
 
























                                                                                                    
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************

    Sega 315-5338A

    I/O Controller

***************************************************************************/

#include "emu.h"
#include "315_5338a.h"

//#define VERBOSE 1
#include "logmacro.h"


//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(SEGA_315_5338A, sega_315_5338a_device, "315_5338a", "Sega 315-5338A I/O Controller")


//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  sega_315_5338a_device - constructor
//-------------------------------------------------

sega_315_5338a_device::sega_315_5338a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, SEGA_315_5338A, tag, owner, clock),
	m_read_cb(*this), m_write_cb(*this),
	m_in_port_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} },
	m_out_port_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} },
	m_port_config(0), m_serial_output(0), m_address(0)
{
	std::fill(std::begin(m_port_value), std::end(m_port_value), 0xff);
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void sega_315_5338a_device::device_start()
{
	// resolve callbacks
	m_read_cb.resolve_safe(0xff);
	m_write_cb.resolve_safe();

	for (unsigned i = 0; i < 7; i++)
	{
		m_in_port_cb[i].resolve_safe(0xff);
		m_out_port_cb[i].resolve_safe();
	}

	// register for save states
	save_pointer(NAME(m_port_value), 7);
	save_item(NAME(m_port_config));
	save_item(NAME(m_serial_output));
	save_item(NAME(m_address));
}


//**************************************************************************
//  INTERFACE
//**************************************************************************

READ8_MEMBER( sega_315_5338a_device::read )
{
	uint8_t data = 0xff;

	switch (offset)
	{
	// port 0 to 6
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:
		if (BIT(m_port_config, offset))
			data = m_in_port_cb[offset](0);
		else
			data = m_port_value[offset];
		break;

	case 0x08: data = m_port_config; break;

	// serial data read back?
	case 0x0a: data = m_serial_output; break;

	// serial data input
	case 0x0c: data = m_read_cb(m_address); break;

	// status register
	case 0x0d:
		// 7654----  unknown
		// ----3---  transfer finished?
		// -----21-  unknown
		// -------0  command acknowledged (0 = ack)
		data = 0x08;
		break;
	}

	LOG("RD %02x = %02x\n", offset, data);

	return data;
}

WRITE8_MEMBER( sega_315_5338a_device::write )
{
	LOG("WR %02x = %02x\n", offset, data);

	switch (offset)
	{
	// port 0 to 6
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:
		m_port_value[offset] = data;
		if (BIT(m_port_config, offset) == 0)
			m_out_port_cb[offset](data);
		break;

	// port direction register (0 = output, 1 = input)
	case 0x08:
		// handle ports that were previously set to input and are now output
		{
			uint8_t changed = data ^ m_port_config;
			for (unsigned i = 0; i < 7; i++)
				if (BIT(changed, i) && BIT(data, i) == 0)
					m_out_port_cb[i](m_port_value[i]);
		}

		m_port_config = data;
		break;

	// command register
	case 0x09:
		switch (data)
		{
		case 0x00:
			m_address = (m_address & 0xff00) | (m_serial_output << 0);
			break;
		case 0x01:
			m_address = (m_address & 0x00ff) | (m_serial_output << 8);
			break;
		case 0x07:
			m_write_cb(m_address, m_serial_output, 0xff);
			break;
		case 0x87:
			// sent after setting up the address and when wanting to receive serial data
			break;
		default:
			logerror("Unknown command: %02x\n", data);
		}
		break;

	// serial data output
	case 0x0a: m_serial_output = data; break;
	}
}