summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/at28c16.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/at28c16.c')
-rw-r--r--trunk/src/emu/machine/at28c16.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/at28c16.c b/trunk/src/emu/machine/at28c16.c
new file mode 100644
index 00000000000..f0584f3fa6f
--- /dev/null
+++ b/trunk/src/emu/machine/at28c16.c
@@ -0,0 +1,294 @@
+/***************************************************************************
+ ATMEL AT28C16
+
+ 16K ( 2K x 8 ) Parallel EEPROM
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/at28c16.h"
+
+#define AT28C16_DATA_BYTES ( 0x800 )
+#define AT28C16_ID_BYTES ( 0x20 )
+#define AT28C16_TOTAL_BYTES ( AT28C16_DATA_BYTES + AT28C16_ID_BYTES )
+
+#define AT28C16_ID_OFFSET ( AT28C16_DATA_BYTES - AT28C16_ID_BYTES )
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+static ADDRESS_MAP_START( at28c16_map8, AS_PROGRAM, 8, at28c16_device )
+ AM_RANGE(0x0000, 0x081f) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type AT28C16 = &device_creator<at28c16_device>;
+
+//-------------------------------------------------
+// at28c16_device - constructor
+//-------------------------------------------------
+
+at28c16_device::at28c16_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock )
+ : device_t(mconfig, AT28C16, "AT28C16", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_a9_12v( 0 ),
+ m_oe_12v( 0 ),
+ m_last_write( -1 )
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void at28c16_device::device_config_complete()
+{
+ m_space_config = address_space_config( "at28c16", ENDIANNESS_BIG, 8, 12, 0, *ADDRESS_MAP_NAME( at28c16_map8 ) );
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+void at28c16_device::device_validity_check(validity_checker &valid) const
+{
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *at28c16_device::memory_space_config( address_spacenum spacenum ) const
+{
+ return ( spacenum == 0 ) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void at28c16_device::device_start()
+{
+ m_write_timer = machine().scheduler().timer_alloc( FUNC(write_finished), this );
+
+ save_item( NAME(m_a9_12v) );
+ save_item( NAME(m_oe_12v) );
+ save_item( NAME(m_last_write) );
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void at28c16_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void at28c16_device::nvram_default()
+{
+ UINT16 default_value = 0xff;
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, default_value );
+ }
+
+ /* populate from a memory region if present */
+ if( m_region != NULL )
+ {
+ if( m_region->bytes() != AT28C16_DATA_BYTES )
+ {
+ fatalerror( "at28c16 region '%s' wrong size (expected size = 0x%X)", tag(), AT28C16_DATA_BYTES );
+ }
+
+ if( m_region->width() != 1 )
+ {
+ fatalerror( "at28c16 region '%s' needs to be an 8-bit region", tag() );
+ }
+
+ for( offs_t offs = 0; offs < AT28C16_DATA_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, m_region->u8( offs ) );
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void at28c16_device::nvram_read( emu_file &file )
+{
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, AT28C16_TOTAL_BYTES );
+
+ file.read( buffer, AT28C16_TOTAL_BYTES );
+
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, buffer[ offs ] );
+ }
+
+ auto_free( machine(), buffer );
+}
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void at28c16_device::nvram_write( emu_file &file )
+{
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, AT28C16_TOTAL_BYTES );
+
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ buffer[ offs ] = m_addrspace[ 0 ]->read_byte( offs );
+ }
+
+ file.write( buffer, AT28C16_TOTAL_BYTES );
+
+ auto_free( machine(), buffer );
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( at28c16_w )
+{
+ downcast<at28c16_device *>( device )->write( offset, data );
+}
+
+void at28c16_device::write( offs_t offset, UINT8 data )
+{
+ if( m_last_write >= 0 )
+ {
+// logerror( "%s: AT28C16: write( %04x, %02x ) busy\n", machine.describe_context(), offset, data );
+ }
+ else if( m_oe_12v )
+ {
+// logerror( "%s: AT28C16: write( %04x, %02x ) erase\n", machine.describe_context(), offset, data );
+ if( m_last_write < 0 )
+ {
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, 0xff );
+ }
+
+ m_last_write = 0xff;
+ m_write_timer->adjust( attotime::from_usec( 200 ) );
+ }
+ }
+ else
+ {
+ if( m_a9_12v && offset >= AT28C16_ID_OFFSET )
+ {
+ offset += AT28C16_ID_BYTES;
+ }
+
+// logerror( "%s: AT28C16: write( %04x, %02x )\n", machine.describe_context(), offset, data );
+ if( m_last_write < 0 && m_addrspace[ 0 ]->read_byte( offset ) != data )
+ {
+ m_addrspace[ 0 ]->write_byte( offset, data );
+ m_last_write = data;
+ m_write_timer->adjust( attotime::from_usec( 200 ) );
+ }
+ }
+}
+
+
+READ8_DEVICE_HANDLER( at28c16_r )
+{
+ return downcast<at28c16_device *>( device )->read( offset );
+}
+
+UINT8 at28c16_device::read( offs_t offset )
+{
+ if( m_last_write >= 0 )
+ {
+ UINT8 data = m_last_write ^ 0x80;
+// logerror( "%s: AT28C16: read( %04x ) write status %02x\n", machine.describe_context(), offset, data );
+ return data;
+ }
+ else
+ {
+ if( m_a9_12v && offset >= AT28C16_ID_OFFSET )
+ {
+ offset += AT28C16_ID_BYTES;
+ }
+
+ UINT8 data = m_addrspace[ 0 ]->read_byte( offset );
+// logerror( "%s: AT28C16: read( %04x ) data %02x\n", machine.describe_context(), offset, data );
+ return data;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( at28c16_a9_12v )
+{
+ downcast<at28c16_device *>( device )->set_a9_12v( state );
+}
+
+void at28c16_device::set_a9_12v( int state )
+{
+ state &= 1;
+ if( m_a9_12v != state )
+ {
+// logerror( "%s: AT28C16: set_a9_12v( %d )\n", machine.describe_context(), state );
+ m_a9_12v = state;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( at28c16_oe_12v )
+{
+ downcast<at28c16_device *>( device )->set_oe_12v( state );
+}
+
+void at28c16_device::set_oe_12v( int state )
+{
+ state &= 1;
+ if( m_oe_12v != state )
+ {
+// logerror( "%s: AT28C16: set_oe_12v( %d )\n", machine.describe_context(), state );
+ m_oe_12v = state;
+ }
+}
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+TIMER_CALLBACK( at28c16_device::write_finished )
+{
+ reinterpret_cast<at28c16_device *>(ptr)->m_last_write = -1;
+}