summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/315_5649.cpp
blob: 909715294f7885e95346b9740c7022b6dbbf6323 (plain) (tree)

































                                                                                                                             





                              
                         
                  











                                                                          

                                            
 
                                            
 

                                           
 
                                     
 



                                            
                                

 







                                                   
                   

 




                                                                            
                                                 





                            







                                                                                                            





                  





                                                       
                                   


                                                      











                                                                                             


                                        



                                                                         






                                              
                                                             











                                              
                                                                                       






                                                          
                                    



                                                  




                                           


                              






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

    Sega 315-5649

    I/O Controller

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

#include "emu.h"
#include "315_5649.h"

#define VERBOSE 1
#include "logmacro.h"


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

DEFINE_DEVICE_TYPE(SEGA_315_5649, sega_315_5649_device, "315_5649", "Sega 315-5649 I/O Controller")


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

//-------------------------------------------------
//  sega_315_5649_device - constructor
//-------------------------------------------------

sega_315_5649_device::sega_315_5649_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, SEGA_315_5649, tag, owner, clock),
	m_in_port_cb(*this),
	m_out_port_cb(*this),
	m_an_port_cb(*this),
	m_serial_rd_cb(*this),
	m_serial_wr_cb(*this),
	m_cnt_cb(*this),
	m_port_config(0),
	m_mode(0),
	m_analog_channel(0)
{
	std::fill(std::begin(m_port_value), std::end(m_port_value), 0xff);
}

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

void sega_315_5649_device::device_start()
{
	// resolve callbacks
	m_in_port_cb.resolve_all_safe(0xff);
	m_out_port_cb.resolve_all_safe();

	m_an_port_cb.resolve_all_safe(0xff);

	m_serial_rd_cb.resolve_all_safe(0);
	m_serial_wr_cb.resolve_all_safe();

	m_cnt_cb.resolve_all_safe(0);

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

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void sega_315_5649_device::device_reset()
{
	// set all ports to input on reset
	m_port_config = 0xff;
	m_mode = 0;
}


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

uint8_t sega_315_5649_device::read(offs_t offset)
{
	uint8_t data = 0xff;

	switch (offset)
	{
	// port a to g
	case 0x06:
		if (m_mode & 0x80) // port G counter mode - 4x 16bit counters, auto-increments
		{
			data = m_cnt_cb[(m_port_value[6] >> 1) & 3](0) >> (((m_port_value[6] & 1) ^ 1) * 8);
			if (!machine().side_effects_disabled())
				m_port_value[6] = (m_port_value[6] & 0xf8) | ((m_port_value[6] + 1) & 7);
			break;
		}
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
		if (BIT(m_port_config, offset))
			data = m_in_port_cb[offset](0);
		else
			data = m_port_value[offset];
		break;

	// RS-422 channel 1/2 input
	case 0x0b: data = m_serial_rd_cb[0](0); break;
	case 0x0c: data = m_serial_rd_cb[1](0); break;

	// RS-422 status
	// 7--- ----  RX2IE
	// -6-- ----  RX1IE some I-error ?
	// --5- ----  RX2FE
	// ---4 ----  RX1FE framing error ?
	// ---- 3---  RX2BF
	// ---- -2--  RX1BF 1 = receive buffer full
	// ---- --1-  TX2BF
	// ---- ---0  TX1BF 1 = transmit buffer full
	case 0x0d:
		data = 0x0c; // HACK, recv buffers always full, transmit buffers always empty
		break;

	// analog input, auto-increments
	case 0x0f:
		data = m_an_port_cb[m_analog_channel](0);
		if (!machine().side_effects_disabled())
			m_analog_channel = (m_analog_channel + 1) & 0x07;
		break;
	}

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

	return data;
}

void sega_315_5649_device::write(offs_t offset, uint8_t data)
{
	LOG("WR %02x = %02x\n", offset, data);

	switch (offset)
	{
	// port a-g
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:  // when in counter mode, bit 7 - 0 reset counters (not implemented)
		m_port_value[offset] = data;
		m_out_port_cb[offset](data);
		break;

	// port direction register (0 = output, 1 = input)
	case 0x08: m_port_config = data; break;

	// RS-422 channel 1/2 output
	case 0x09: m_serial_wr_cb[0](data); break;
	case 0x0a: m_serial_wr_cb[1](data); break;

	// mode register
	// 7--- ----  port G counter mode
	// -6-- ----  ?
	// --5- ----  RS-422 satellite mode
	// ---4 ----  RS-422 loopback
	// ---- 3210  RS-422 satellite N#
	case 0x0e:
		m_mode = data;
		break;

	// analog mux select
	case 0x0f:
		m_analog_channel = data & 0x07;
		break;
	}
}