summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i2cmem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/i2cmem.cpp')
-rw-r--r--src/devices/machine/i2cmem.cpp47
1 files changed, 25 insertions, 22 deletions
diff --git a/src/devices/machine/i2cmem.cpp b/src/devices/machine/i2cmem.cpp
index f7ab143d5b9..11ae47ab74d 100644
--- a/src/devices/machine/i2cmem.cpp
+++ b/src/devices/machine/i2cmem.cpp
@@ -30,6 +30,7 @@ Up to 4096 bytes can be addressed.
#define STATE_BYTEADDR ( 2 )
#define STATE_DATAIN ( 3 )
#define STATE_DATAOUT ( 4 )
+#define STATE_RESET ( 5 )
#define DEVSEL_RW ( 1 )
#define DEVSEL_ADDRESS ( 0xfe )
@@ -101,8 +102,7 @@ i2cmem_device::i2cmem_device(
m_shift(0),
m_byteaddr(0),
m_page_offset(0),
- m_page_written_size(0),
- m_in_write(false)
+ m_page_written_size(0)
{
// these memories work off the I2C clock only
assert(!clock);
@@ -174,7 +174,6 @@ void i2cmem_device::device_start()
save_item( NAME(m_shift) );
save_item( NAME(m_devsel) );
save_item( NAME(m_byteaddr) );
- save_item( NAME(m_in_write) );
save_item( NAME(m_page_offset) );
save_item( NAME(m_page_written_size) );
save_pointer( &m_data[0], "m_data", m_data_size );
@@ -186,16 +185,6 @@ void i2cmem_device::device_start()
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void i2cmem_device::device_reset()
-{
- m_in_write = false;
-}
-
-
-//-------------------------------------------------
// nvram_default - called to initialize NVRAM to
// its default state
//-------------------------------------------------
@@ -293,13 +282,12 @@ WRITE_LINE_MEMBER( i2cmem_device::write_sda )
{
if( m_sdaw )
{
- if( m_in_write )
+ if( m_state == STATE_DATAIN && m_page_size > 0 )
{
int base = data_offset();
int root = base & ~( m_page_size - 1);
for( int i=0; i < m_page_written_size; i++)
m_data[root | ((base + i) & (m_page_size - 1))] = m_page[i];
- m_in_write = false;
verboselog( this, 1, "data[ %04x to %04x ] = %x bytes\n", base, root | ((base + m_page_written_size - 1) & (m_page_size - 1)), m_page_written_size );
}
verboselog( this, 1, "stop\n" );
@@ -346,7 +334,15 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
case STATE_DEVSEL:
m_devsel = m_shift;
- if( !select_device() )
+ if( m_devsel == 0 )
+ {
+ // TODO: Atmel datasheets document 2-wire software reset, but doesn't mention it will lower sda only that it will release it.
+ // ltv_naru however requires it to be lowered, but we don't currently know the manufacturer of the chip used.
+ verboselog( this, 1, "software reset\n" );
+ m_state = STATE_RESET;
+ m_sdar = 0;
+ }
+ else if( !select_device() )
{
verboselog( this, 1, "devsel %02x: not this device\n", m_devsel );
m_state = STATE_IDLE;
@@ -364,11 +360,11 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
break;
case STATE_BYTEADDR:
- m_byteaddr = m_shift;
+ m_byteaddr = ((m_devsel << 7) & 0xff00) | m_shift;
m_page_offset = 0;
m_page_written_size = 0;
- verboselog( this, 1, "byteaddr %02x\n", m_byteaddr );
+ verboselog( this, 1, "byteaddr %02x\n", m_shift );
m_state = STATE_DATAIN;
break;
@@ -381,7 +377,6 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
}
else if( m_page_size > 0 )
{
- m_in_write = true;
m_page[ m_page_offset ] = m_shift;
verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] );
@@ -447,9 +442,8 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
{
if( m_sdaw )
{
- verboselog( this, 1, "sleep\n" );
+ verboselog( this, 1, "nack\n" );
m_state = STATE_IDLE;
- m_sdar = 0;
}
m_bits++;
@@ -467,6 +461,15 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
}
}
break;
+
+ case STATE_RESET:
+ if( m_scl )
+ {
+ verboselog(this, 1, "software reset ack\n");
+ m_state = STATE_IDLE;
+ m_sdar = 1;
+ }
+ break;
}
}
}
@@ -517,5 +520,5 @@ int i2cmem_device::select_device()
int i2cmem_device::data_offset()
{
- return ( ( ( m_devsel << 7 ) & 0xff00 ) | ( m_byteaddr & 0xff ) ) & address_mask();
+ return m_byteaddr & address_mask();
}