summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/nmc9306.cpp
blob: d20e77a398b0eb3bbd3b72123aa9dc17f1e63728 (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"

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



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

#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
DEFINE_DEVICE_TYPE(NMC9306, nmc9306_device, "nmc9306", "NMC9306 EEPROM")

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

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


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

inline void nmc9306_device::write(offs_t offset, uint16_t 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_t clock)
	: device_t(mconfig, NMC9306, tag, owner, clock),
		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:
		LOG("NMC9306 Idle %u\n", m_di);

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

	case STATE_COMMAND:
		LOG("NMC9306 Command Bit %u\n", 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:
		LOG("NMC9306 Address Bit %u\n", 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:
					LOG("NMC9306 EWDS\n");
					m_ewen = false;
					m_state = STATE_IDLE;
					break;

				case WRAL:
					LOG("NMC9306 WRAL\n");
					break;

				case ERAL:
					LOG("NMC9306 ERAL\n");
					break;

				case EWEN:
					LOG("NMC9306 EWEN\n");
					m_ewen = true;
					m_state = STATE_IDLE;
					break;
				}
				break;

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

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

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

			m_bits = 0;
		}
		break;

	case STATE_DATA_IN:
		LOG("NMC9306 Data Bit IN %u\n", 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:
		LOG("NMC9306 Data Bit OUT %u\n", 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;
}