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

                              



                                                                            
                                                     



                                                                            




                    


                                                                            
 
                 









                                         
 
 
                                                                            
               

                                                                            






                                                            
                                                                                                             
                                                                                                



                          
                                                                                                         
 

 


                                                   
 


                                   




                                    

                                       






                                 
















                                                   
 
 
                                       
 



                          
                            
                 
                                                                                                                                           
                 





                            
                                       
                 
                                           
                 
                             


                      
                                       
                 
                                           
                 
                             




                                  
                                               
                         
                                                                            
                         
                                     


                    
                                               
                         
                                                                                   
                         
                                     






                      
                                              
 
                       

                                                 

                   
                                                                         
         

 
                                              
 
                       

                                                 

                   
                                                                         
         

 
                                        
 

                          
                            
                 
                                                                                                                                                     
                 





                       
                                                


                      
                                                


                      
                            
                 
                                                                                                                           
                 
 
                              


                      
                            
                 
                                                                                                                           
                 
 
                              


                      
                            
                 
                                                                                                                          
                 
 
                             







                                          
                                                                                    


                            
                                                                                           






                                          
                                                                                      


                            
                                                                                             





                         
// license:GPL-2.0+
// copyright-holders:Dirk Best
/***************************************************************************

    National Semiconductor INS8154

    N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)

    TODO: Strobed modes

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

#include "emu.h"
#include "ins8154.h"


/***************************************************************************
    CONSTANTS
***************************************************************************/

#define VERBOSE 1

/* Mode Definition Register */
enum
{
	MDR_BASIC                 = 0x00,
	MDR_STROBED_INPUT         = 0x20,
	MDR_STROBED_OUTPUT        = 0x60,
	MDR_STROBED_OUTPUT_3STATE = 0xe0
};



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

// device type definition
const device_type INS8154 = &device_creator<ins8154_device>;

//-------------------------------------------------
//  ins8154_device - constructor
//-------------------------------------------------

ins8154_device::ins8154_device(const machine_config &mconfig, std::string tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, INS8154, "INS8154 RAM I/O", tag, owner, clock, "ins8154", __FILE__),
	m_in_a_cb(*this),
	m_out_a_cb(*this),
	m_in_b_cb(*this),
	m_out_b_cb(*this),
	m_out_irq_cb(*this), m_in_a(0), m_in_b(0), m_out_a(0), m_out_b(0), m_mdr(0), m_odra(0), m_odrb(0)
{
}

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

void ins8154_device::device_start()
{
	/* resolve callbacks */
	m_in_a_cb.resolve();
	m_out_a_cb.resolve_safe();
	m_in_b_cb.resolve();
	m_out_b_cb.resolve_safe();
	m_out_irq_cb.resolve_safe();

	/* register for state saving */
	save_item(NAME(m_in_a));
	save_item(NAME(m_in_b));
	save_item(NAME(m_out_a));
	save_item(NAME(m_out_b));
	save_item(NAME(m_mdr));
	save_item(NAME(m_odra));
	save_item(NAME(m_odrb));
}


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

void ins8154_device::device_reset()
{
	m_in_a = 0;
	m_in_b = 0;
	m_out_a = 0;
	m_out_b = 0;
	m_mdr = 0;
	m_odra = 0;
	m_odrb = 0;
}


READ8_MEMBER(ins8154_device::ins8154_r)
{
	UINT8 val = 0xff;

	if (offset > 0x24)
	{
		if (VERBOSE)
		{
			logerror("%s: INS8154 '%s' Read from invalid offset %02x!\n", machine().describe_context(), tag().c_str(), offset);
		}
		return 0xff;
	}

	switch (offset)
	{
	case 0x20:
		if(!m_in_a_cb.isnull())
		{
			val = m_in_a_cb(0);
		}
		m_in_a = val;
		break;

	case 0x21:
		if(!m_in_b_cb.isnull())
		{
			val = m_in_b_cb(0);
		}
		m_in_b = val;
		break;

	default:
		if (offset < 0x08)
		{
			if(!m_in_a_cb.isnull())
			{
				val = (m_in_a_cb(0) << (8 - offset)) & 0x80;
			}
			m_in_a = val;
		}
		else
		{
			if(!m_in_b_cb.isnull())
			{
				val = (m_in_b_cb(0) << (8 - (offset >> 4))) & 0x80;
			}
			m_in_b = val;
		}
		break;
	}

	return val;
}

WRITE8_MEMBER(ins8154_device::ins8154_porta_w)
{
	m_out_a = data;

	/* Test if any pins are set as outputs */
	if (m_odra)
	{
		m_out_a_cb((offs_t)0, (data & m_odra) | (m_odra ^ 0xff));
	}
}

WRITE8_MEMBER(ins8154_device::ins8154_portb_w)
{
	m_out_b = data;

	/* Test if any pins are set as outputs */
	if (m_odrb)
	{
		m_out_b_cb((offs_t)0, (data & m_odrb) | (m_odrb ^ 0xff));
	}
}

WRITE8_MEMBER(ins8154_device::ins8154_w)
{
	if (offset > 0x24)
	{
		if (VERBOSE)
		{
			logerror("%s: INS8154 '%s' Write %02x to invalid offset %02x!\n", machine().describe_context(), tag().c_str(), data, offset);
		}
		return;
	}

	switch (offset)
	{
	case 0x20:
		ins8154_porta_w(space, 0, data);
		break;

	case 0x21:
		ins8154_portb_w(space, 0, data);
		break;

	case 0x22:
		if (VERBOSE)
		{
			logerror("%s: INS8154 '%s' ODRA set to %02x\n", machine().describe_context(), tag().c_str(), data);
		}

		m_odra = data;
		break;

	case 0x23:
		if (VERBOSE)
		{
			logerror("%s: INS8154 '%s' ODRB set to %02x\n", machine().describe_context(), tag().c_str(), data);
		}

		m_odrb = data;
		break;

	case 0x24:
		if (VERBOSE)
		{
			logerror("%s: INS8154 '%s' MDR set to %02x\n", machine().describe_context(), tag().c_str(), data);
		}

		m_mdr = data;
		break;

	default:
		if (offset & 0x10)
		{
			/* Set bit */
			if (offset < 0x08)
			{
				ins8154_porta_w(space, 0, m_out_a |= offset & 0x07);
			}
			else
			{
				ins8154_portb_w(space, 0, m_out_b |= (offset >> 4) & 0x07);
			}
		}
		else
		{
			/* Clear bit */
			if (offset < 0x08)
			{
				ins8154_porta_w(space, 0, m_out_a & ~(offset & 0x07));
			}
			else
			{
				ins8154_portb_w(space, 0, m_out_b & ~((offset >> 4) & 0x07));
			}
		}

		break;
	}
}