summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author smf- <smf-@users.noreply.github.com>2020-03-02 11:58:36 +0000
committer smf- <smf-@users.noreply.github.com>2020-03-02 11:59:02 +0000
commit635f469c7dd0b5166455bafeddb0e898b1081165 (patch)
tree6b5b3d91a2f5293f9e98da5dbd74d851f7b2246e /src/devices
parente116b72bc91ae640549213544822b8a5731608f3 (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.cpp47
-rw-r--r--src/devices/machine/i2cmem.h2
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) \