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.cpp205
1 files changed, 106 insertions, 99 deletions
diff --git a/src/devices/machine/i2cmem.cpp b/src/devices/machine/i2cmem.cpp
index e21d8c6b6ee..8b6358eceac 100644
--- a/src/devices/machine/i2cmem.cpp
+++ b/src/devices/machine/i2cmem.cpp
@@ -30,8 +30,9 @@ constexpr int STATE_DEVSEL(1);
constexpr int STATE_ADDRESSHIGH(2);
constexpr int STATE_ADDRESSLOW(3);
constexpr int STATE_DATAIN(4);
-constexpr int STATE_DATAOUT(5);
-constexpr int STATE_RESET(6);
+constexpr int STATE_READSELACK(5);
+constexpr int STATE_DATAOUT(6);
+constexpr int STATE_RESET(7);
constexpr int DEVSEL_RW(1);
constexpr int DEVSEL_ADDRESS(0xfe);
@@ -368,110 +369,112 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
{
if( m_scl )
{
- switch( m_state )
+ m_bits++;
+ }
+ else
+ {
+ if( m_bits == 8 )
{
- case STATE_DEVSEL:
- m_devsel = m_shift;
-
- if( m_devsel == 0 && !m_devsel_address_low )
- {
- // 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() )
+ switch( m_state )
{
- verboselog( this, 1, "devsel %02x: not this device\n", m_devsel );
- m_state = STATE_IDLE;
- }
- else if( ( m_devsel & DEVSEL_RW ) == 0 )
- {
- if (m_devsel_address_low)
+ case STATE_DEVSEL:
+ m_devsel = m_shift;
+
+ if( m_devsel == 0 && !m_devsel_address_low )
{
- verboselog( this, 1, "devsel %02x: write (Xicor special, address %02x)\n", m_devsel, m_devsel >> 1);
- m_byteaddr = (m_devsel & DEVSEL_ADDRESS) >> 1;
- m_page_offset = 0;
- m_page_written_size = 0;
- m_state = STATE_DATAIN;
+ // 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;
}
- else
+ else if( !select_device() )
{
- verboselog( this, 1, "devsel %02x: write\n", m_devsel );
- m_state = skip_addresshigh() ? STATE_ADDRESSLOW : STATE_ADDRESSHIGH;
+ verboselog( this, 1, "devsel %02x: not this device\n", m_devsel );
+ m_state = STATE_IDLE;
}
- }
- else
- {
- if (m_devsel_address_low)
+ else if( ( m_devsel & DEVSEL_RW ) == 0 )
{
- verboselog( this, 1, "devsel %02x: read (Xicor special, address %02x)\n", m_devsel, m_devsel >> 1);
- m_byteaddr = (m_devsel & DEVSEL_ADDRESS) >> 1;
+ if (m_devsel_address_low)
+ {
+ verboselog( this, 1, "devsel %02x: write (Xicor special, address %02x)\n", m_devsel, m_devsel >> 1);
+ m_byteaddr = (m_devsel & DEVSEL_ADDRESS) >> 1;
+ m_page_offset = 0;
+ m_page_written_size = 0;
+ m_state = STATE_DATAIN;
+ }
+ else
+ {
+ verboselog( this, 1, "devsel %02x: write\n", m_devsel );
+ m_state = skip_addresshigh() ? STATE_ADDRESSLOW : STATE_ADDRESSHIGH;
+ }
}
else
{
- verboselog( this, 1, "devsel %02x: read\n", m_devsel );
+ if (m_devsel_address_low)
+ {
+ verboselog( this, 1, "devsel %02x: read (Xicor special, address %02x)\n", m_devsel, m_devsel >> 1);
+ m_byteaddr = (m_devsel & DEVSEL_ADDRESS) >> 1;
+ }
+ else
+ {
+ verboselog( this, 1, "devsel %02x: read\n", m_devsel );
+ }
+ m_state = STATE_READSELACK;
}
- m_state = STATE_DATAOUT;
- }
- break;
+ break;
- case STATE_ADDRESSHIGH:
- m_addresshigh = m_shift;
+ case STATE_ADDRESSHIGH:
+ m_addresshigh = m_shift;
- verboselog(this, 1, "addresshigh %02x\n", m_addresshigh);
+ verboselog(this, 1, "addresshigh %02x\n", m_addresshigh);
- m_state = STATE_ADDRESSLOW;
- break;
+ m_state = STATE_ADDRESSLOW;
+ break;
- case STATE_ADDRESSLOW:
- m_byteaddr = m_shift | (skip_addresshigh() ? ((m_devsel & DEVSEL_ADDRESS) << 7) & address_mask() : m_addresshigh << 8);
- m_page_offset = 0;
- m_page_written_size = 0;
+ case STATE_ADDRESSLOW:
+ m_byteaddr = m_shift | (skip_addresshigh() ? ((m_devsel & DEVSEL_ADDRESS) << 7) & address_mask() : m_addresshigh << 8);
+ m_page_offset = 0;
+ m_page_written_size = 0;
- verboselog( this, 1, "addresslow %02x (byteaddr %04x)\n", m_shift, m_byteaddr );
+ verboselog( this, 1, "addresslow %02x (byteaddr %04x)\n", m_shift, m_byteaddr );
- m_state = STATE_DATAIN;
- break;
+ m_state = STATE_DATAIN;
+ break;
- case STATE_DATAIN:
- if( m_wc )
- {
- verboselog( this, 0, "write not enabled\n" );
- m_state = STATE_IDLE;
- }
- else if( m_write_page_size > 0 )
- {
- m_page[ m_page_offset ] = m_shift;
- verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] );
-
- m_page_offset++;
- if( m_page_offset == m_write_page_size )
- m_page_offset = 0;
- m_page_written_size++;
- if( m_page_written_size > m_write_page_size)
- m_page_written_size = m_write_page_size;
- }
- else
- {
- int offset = data_offset();
+ case STATE_DATAIN:
+ if( m_wc )
+ {
+ verboselog( this, 0, "write not enabled\n" );
+ m_state = STATE_IDLE;
+ }
+ else if( m_write_page_size > 0 )
+ {
+ m_page[ m_page_offset ] = m_shift;
+ verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] );
+
+ m_page_offset++;
+ if( m_page_offset == m_write_page_size )
+ m_page_offset = 0;
+ m_page_written_size++;
+ if( m_page_written_size > m_write_page_size)
+ m_page_written_size = m_write_page_size;
+ }
+ else
+ {
+ int offset = data_offset();
- verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift );
- m_data[ offset ] = m_shift;
+ verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift );
+ m_data[ offset ] = m_shift;
- m_byteaddr++;
+ m_byteaddr++;
+ }
+ break;
+ }
+
+ if( m_state != STATE_IDLE )
+ {
+ m_sdar = 0 ;
}
- break;
- }
-
- m_bits++;
- }
- else
- {
- if( m_bits == 8 )
- {
- m_sdar = 0;
}
else
{
@@ -482,11 +485,20 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
}
break;
+ case STATE_READSELACK:
+ m_bits = 0;
+ m_state = STATE_DATAOUT;
+ break;
+
case STATE_DATAOUT:
if( m_bits < 8 )
{
if( m_scl )
{
+ m_bits++;
+ }
+ else
+ {
if( m_bits == 0 )
{
int offset = data_offset();
@@ -499,7 +511,6 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
m_sdar = ( m_shift >> 7 ) & 1;
m_shift = ( m_shift << 1 ) & 0xff;
- m_bits++;
}
}
else
@@ -512,18 +523,11 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
m_state = STATE_IDLE;
}
- m_bits++;
+ m_bits = 0;
}
else
{
- if( m_bits == 8 )
- {
- m_sdar = 1;
- }
- else
- {
- m_bits = 0;
- }
+ m_sdar = 1;
}
}
break;
@@ -531,9 +535,13 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
case STATE_RESET:
if( m_scl )
{
- verboselog(this, 1, "software reset ack\n");
- m_state = STATE_IDLE;
- m_sdar = 1;
+ if( m_bits > 8 )
+ {
+ verboselog(this, 1, "software reset ack\n");
+ m_state = STATE_IDLE;
+ m_sdar = 1;
+ }
+ m_bits++;
}
break;
}
@@ -555,7 +563,6 @@ WRITE_LINE_MEMBER( i2cmem_device::write_wc )
READ_LINE_MEMBER( i2cmem_device::read_sda )
{
int res = m_sdar & 1;
-
verboselog( this, 2, "read sda %d\n", res );
return res;