summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/lh5810.cpp
blob: 8e427ab3bcff39d4805071b25f69c27df5dbfd3e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

                                 










                                                                       

                   




















                                                                           



                                                                            
                                                                      
 







                                                                            
                                                                                                             







                                                      










                                                   





                                     



































                                                   
                                                                         









                                                                                                 
                                                                                                                     


                                             

                                                                                                                     
















































                                                                                                          
                                                               



                                                                                                          

                                                                                                                    



                                             
                                                               


                              
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
/**********************************************************************

    LH5810/LH5811 Input/Output Port Controller

    TODO:
    - serial data transfer
    - data transfer to the cassette tape

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

#include "emu.h"
#include "lh5810.h"

//*************************************************************************
//  MACROS / CONSTANTS
//*************************************************************************

enum
{
	LH5810_RESET = 4,
	LH5810_U,
	LH5810_L,
	LH5820_F,
	LH5810_OPC,
	LH5810_G,
	LH5810_MSK,
	LH5810_IF,
	LH5810_DDA,
	LH5810_DDB,
	LH5810_OPA,
	LH5810_OPB
};


//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

DEFINE_DEVICE_TYPE(LH5810, lh5810_device, "lh5810", "LH5810 I/O Port")

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

//-------------------------------------------------
//  lh5810_device - constructor
//-------------------------------------------------

lh5810_device::lh5810_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, LH5810, tag, owner, clock)
	, m_porta_r_cb(*this)
	, m_porta_w_cb(*this)
	, m_portb_r_cb(*this)
	, m_portb_w_cb(*this)
	, m_portc_w_cb(*this)
	, m_out_int_cb(*this)
	, m_irq(0)
{
}


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

void lh5810_device::device_start()
{
	// resolve callbacks
	m_porta_r_cb.resolve_safe(0);
	m_porta_w_cb.resolve_safe();
	m_portb_r_cb.resolve_safe(0);
	m_portb_w_cb.resolve_safe();
	m_portc_w_cb.resolve_safe();
	m_out_int_cb.resolve_safe();

	// 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_cb(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_cb(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_cb(0) & ~m_reg[LH5810_DDB]);
			m_out_int_cb((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_cb((offs_t)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_cb((offs_t)0, m_reg[offset]);
			m_out_int_cb((m_reg[offset] & 0x80 && m_reg[LH5810_MSK] & 0x02) ? ASSERT_LINE : CLEAR_LINE);
			break;

		case LH5810_OPC:
			m_reg[offset] = data;
			m_portc_w_cb((offs_t)0, m_reg[offset]);
			break;
	}
}