diff options
author | 2020-03-02 11:58:36 +0000 | |
---|---|---|
committer | 2020-03-02 11:59:02 +0000 | |
commit | 635f469c7dd0b5166455bafeddb0e898b1081165 (patch) | |
tree | 6b5b3d91a2f5293f9e98da5dbd74d851f7b2246e /src/devices | |
parent | e116b72bc91ae640549213544822b8a5731608f3 (diff) |
Latch the upper address bits from the i2c device id after receiving the lower 8 bits of the address, implement 2-wire software reset for i2c, stop nack from lowering sda, remove redundant state from i2c page write. [smf]
Change Xavix2 port0 to pull sda from i2cmem when reading the data register and the bit has been set to an input, instead of when changing the ddr to an input or changing the clock output.
Diffstat (limited to 'src/devices')
-rw-r--r-- | src/devices/machine/i2cmem.cpp | 47 | ||||
-rw-r--r-- | src/devices/machine/i2cmem.h | 2 |
2 files changed, 25 insertions, 24 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(); } diff --git a/src/devices/machine/i2cmem.h b/src/devices/machine/i2cmem.h index 0cfccc6f9c2..e997af51642 100644 --- a/src/devices/machine/i2cmem.h +++ b/src/devices/machine/i2cmem.h @@ -59,7 +59,6 @@ protected: // device-level overrides virtual void device_start() override; - virtual void device_reset() override; // device_nvram_interface overrides virtual void nvram_default() override; @@ -93,7 +92,6 @@ protected: std::vector<uint8_t> m_page; int m_page_offset; int m_page_written_size; - bool m_in_write; }; #define DECLARE_I2C_DEVICE(name) \ |