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

                               



                                                                       



                                                                       















                                                                            


                                                  




                     


                                              
                                             















                                                                            


                                                                            


                                                            












































                                                                            
                                                                                                             
                                                                                        


                                                       









                                                   

                                                  






























































                                                   
 
                                   
 


                        
                                                                         
 






                                                
 
                           
                                                                                
 


                                  
 





                                                
 
                           
                                                                                
 


                                  
 







                                                         
                                                                                        


                                                             
 
                                          
                                                                                        
                                              
 
                                          
                                                                                        


                                              
                                                                                        






                                                             
                                                                                                      

                                                        
 
                                  
                                                                                                     


                                                                
 
                                   
                                                                                                      



                                                        
 


                                   
 
                           
                                                                                
 


                               
 


                                                        
 


                                             
 
                            
                                                                                 
 


                                       
 


























                                                   
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************

    National Semiconductor NMC9306 256-Bit Serial EEPROM emulation

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

#include "emu.h"
#include "nmc9306.h"



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

#define LOG 1

#define RAM_SIZE 32


// instructions
enum
{
	OTHER = 0,
	WRITE,          // write register A3A2A1A0
	READ,           // read register  A3A2A1A0
	ERASE           // erase register A3A2A1A0
};

// other instructions
enum
{
	EWDS = 0,       // erase/write disable
	WRAL,           // write all registers
	ERAL,           // erase all registers
	EWEN            // erase/write enable
};

// states
enum
{
	STATE_IDLE = 0,
	STATE_COMMAND,
	STATE_ADDRESS,
	STATE_DATA_IN,
	STATE_DATA_OUT,
	STATE_ERASE
};



//**************************************************************************
//  INLINE HELPERS
//**************************************************************************

// device type definition
const device_type NMC9306 = &device_creator<nmc9306_device>;

//-------------------------------------------------
//  nmc9306_device - constructor
//-------------------------------------------------

inline UINT16 nmc9306_device::read(offs_t offset)
{
	return m_register[offset];
}


//-------------------------------------------------
//  nmc9306_device - constructor
//-------------------------------------------------

inline void nmc9306_device::write(offs_t offset, UINT16 data)
{
	if (m_ewen)
	{
		m_register[offset] &= data;
	}
}


//-------------------------------------------------
//  nmc9306_device - constructor
//-------------------------------------------------

inline void nmc9306_device::erase(offs_t offset)
{
	if (m_ewen)
	{
		m_register[offset] = 0xffff;
	}
}



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

//-------------------------------------------------
//  nmc9306_device - constructor
//-------------------------------------------------

nmc9306_device::nmc9306_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, NMC9306, "NMC9306", tag, owner, clock, "nmc9306", __FILE__),
		device_nvram_interface(mconfig, *this),
		m_state(STATE_IDLE),
		m_ewen(false)
{
}


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

void nmc9306_device::device_start()
{
	memset(m_register, 0, sizeof(m_register));

	// state saving
	save_item(NAME(m_bits));
	save_item(NAME(m_state));
	save_item(NAME(m_command));
	save_item(NAME(m_address));
	save_item(NAME(m_data));
	save_item(NAME(m_ewen));
	save_item(NAME(m_cs));
	save_item(NAME(m_sk));
	save_item(NAME(m_do));
	save_item(NAME(m_di));
}


//-------------------------------------------------
//  nvram_default - called to initialize NVRAM to
//  its default state
//-------------------------------------------------

void nmc9306_device::nvram_default()
{
}


//-------------------------------------------------
//  nvram_read - called to read NVRAM from the
//  .nv file
//-------------------------------------------------

void nmc9306_device::nvram_read(emu_file &file)
{
	file.read(m_register, RAM_SIZE);
}


//-------------------------------------------------
//  nvram_write - called to write NVRAM to the
//  .nv file
//-------------------------------------------------

void nmc9306_device::nvram_write(emu_file &file)
{
	file.write(m_register, RAM_SIZE);
}


//-------------------------------------------------
//  cs_w - chip select input
//-------------------------------------------------

WRITE_LINE_MEMBER( nmc9306_device::cs_w )
{
	m_cs = state;
}


//-------------------------------------------------
//  ck_w - serial clock input
//-------------------------------------------------

WRITE_LINE_MEMBER( nmc9306_device::sk_w )
{
	m_sk = state;

	if (!m_cs || !m_sk) return;

	switch (m_state)
	{
	case STATE_IDLE:
		if (LOG) logerror("NMC9306 '%s' Idle %u\n", tag(), m_di);

		if (m_di)
		{
			// start bit received
			m_state = STATE_COMMAND;
			m_bits = 0;
		}
		break;

	case STATE_COMMAND:
		if (LOG) logerror("NMC9306 '%s' Command Bit %u\n", tag(), m_di);

		m_command <<= 1;
		m_command |= m_di;
		m_bits++;

		if (m_bits == 4)
		{
			m_state = STATE_ADDRESS;
			m_bits = 0;
		}
		break;

	case STATE_ADDRESS:
		if (LOG) logerror("NMC9306 '%s' Address Bit %u\n", tag(), m_di);

		m_address <<= 1;
		m_address |= m_di;
		m_bits++;

		if (m_bits == 4)
		{
			switch ((m_command >> 2) & 0x03)
			{
			case OTHER:
				switch (m_command & 0x03)
				{
				case EWDS:
					if (LOG) logerror("NMC9306 '%s' EWDS\n", tag());
					m_ewen = false;
					m_state = STATE_IDLE;
					break;

				case WRAL:
					if (LOG) logerror("NMC9306 '%s' WRAL\n", tag());
					break;

				case ERAL:
					if (LOG) logerror("NMC9306 '%s' ERAL\n", tag());
					break;

				case EWEN:
					if (LOG) logerror("NMC9306 '%s' EWEN\n", tag());
					m_ewen = true;
					m_state = STATE_IDLE;
					break;
				}
				break;

			case WRITE:
				if (LOG) logerror("NMC9306 '%s' WRITE %u\n", tag(), m_address & 0x0f);
				m_state = STATE_DATA_IN;
				break;

			case READ:
				if (LOG) logerror("NMC9306 '%s' READ %u\n", tag(), m_address & 0x0f);
				m_data = read(m_address & 0x0f);
				m_state = STATE_DATA_OUT;
				break;

			case ERASE:
				if (LOG) logerror("NMC9306 '%s' ERASE %u\n", tag(), m_address & 0x0f);
				erase(m_address & 0x0f);
				m_state = STATE_ERASE;
				break;
			}

			m_bits = 0;
		}
		break;

	case STATE_DATA_IN:
		if (LOG) logerror("NMC9306 '%s' Data Bit IN %u\n", tag(), m_di);

		m_data <<= 1;
		m_data |= m_di;
		m_bits++;

		if (m_bits == 16)
		{
			write(m_address & 0x0f, m_data);

			m_state = STATE_IDLE;
		}
		break;

	case STATE_DATA_OUT:
		if (LOG) logerror("NMC9306 '%s' Data Bit OUT %u\n", tag(), m_di);

		m_do = BIT(m_data, 15);
		m_data <<= 1;
		m_bits++;

		if (m_bits == 16)
		{
			m_state = STATE_IDLE;
		}
		break;
	}
}


//-------------------------------------------------
//  di_w - serial data input
//-------------------------------------------------

WRITE_LINE_MEMBER( nmc9306_device::di_w )
{
	m_di = state;
}


//-------------------------------------------------
//  do_r - serial data output
//-------------------------------------------------

READ_LINE_MEMBER( nmc9306_device::do_r )
{
	return m_do;
}