diff options
Diffstat (limited to 'src/devices/machine/i2cmem.cpp')
-rw-r--r-- | src/devices/machine/i2cmem.cpp | 47 |
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(); } |