i2cmem.cpp and derived devices: Only acknowledge correct I2C device-id. (#9630)

* Updated machine/acorn_bmu.cpp, machine/i2cmem.cpp, machine/pcf8573.cpp and machine/machine/pcf8583.cpp.
* Check device ID and only acknowledge device’s own ID.
* Release SDA line to be pulled up when idle.
* aa310.cpp: Combine SDA lines with logical AND.
This commit is contained in:
Paul-Arnold 2022-04-27 15:27:06 +01:00 committed by GitHub
parent 508383295d
commit 4cb71c31d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 385 additions and 356 deletions

View File

@ -96,57 +96,60 @@ WRITE_LINE_MEMBER(acorn_bmu_device::scl_w)
{
if (m_scl)
{
switch (m_state)
{
case STATE_DEVSEL:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_devsel);
m_state = STATE_REGISTER;
}
else
{
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_devsel);
m_state = STATE_DATAOUT;
}
break;
case STATE_REGISTER:
m_register = m_shift;
LOGMASKED(LOG_DATA, "register %02x\n", m_register);
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
LOGMASKED(LOG_DATA, "register[ %02x ] <- %02x\n", m_register, m_shift);
switch (m_register)
{
case BMU_CHARGE_ESTIMATE:
m_estimate = m_shift;
break;
}
m_register++;
break;
}
m_bits++;
}
else
{
if (m_bits == 8)
{
m_sdar = 0;
switch (m_state)
{
case STATE_DEVSEL:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_devsel);
m_state = STATE_REGISTER;
}
else
{
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_devsel);
m_state = STATE_READSELACK;
}
break;
case STATE_REGISTER:
m_register = m_shift;
LOGMASKED(LOG_DATA, "register %02x\n", m_register);
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
LOGMASKED(LOG_DATA, "register[ %02x ] <- %02x\n", m_register, m_shift);
switch (m_register)
{
case BMU_CHARGE_ESTIMATE:
m_estimate = m_shift;
break;
}
m_register++;
break;
}
if( m_state != STATE_IDLE )
{
m_sdar = 0 ;
}
}
else
{
@ -157,10 +160,19 @@ WRITE_LINE_MEMBER(acorn_bmu_device::scl_w)
}
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)
{
@ -194,7 +206,6 @@ WRITE_LINE_MEMBER(acorn_bmu_device::scl_w)
m_sdar = (m_shift >> 7) & 1;
m_shift = (m_shift << 1) & 0xff;
m_bits++;
}
}
else
@ -207,18 +218,11 @@ WRITE_LINE_MEMBER(acorn_bmu_device::scl_w)
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;

View File

@ -45,7 +45,7 @@ private:
int m_devsel;
int m_register;
enum { STATE_IDLE, STATE_DEVSEL, STATE_REGISTER, STATE_DATAIN, STATE_DATAOUT };
enum { STATE_IDLE, STATE_DEVSEL, STATE_REGISTER, STATE_DATAIN, STATE_DATAOUT, STATE_READSELACK };
// registers
enum

View File

@ -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 )
{
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() )
{
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)
{
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
{
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_DATAOUT;
}
break;
case STATE_ADDRESSHIGH:
m_addresshigh = m_shift;
verboselog(this, 1, "addresshigh %02x\n", m_addresshigh);
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;
verboselog( this, 1, "addresslow %02x (byteaddr %04x)\n", m_shift, m_byteaddr );
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();
verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift );
m_data[ offset ] = m_shift;
m_byteaddr++;
}
break;
}
m_bits++;
}
else
{
if( m_bits == 8 )
{
m_sdar = 0;
switch( m_state )
{
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;
}
else if( !select_device() )
{
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)
{
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
{
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;
}
break;
case STATE_ADDRESSHIGH:
m_addresshigh = m_shift;
verboselog(this, 1, "addresshigh %02x\n", m_addresshigh);
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;
verboselog( this, 1, "addresslow %02x (byteaddr %04x)\n", m_shift, m_byteaddr );
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();
verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift );
m_data[ offset ] = m_shift;
m_byteaddr++;
}
break;
}
if( m_state != STATE_IDLE )
{
m_sdar = 0 ;
}
}
else
{
@ -482,10 +485,19 @@ 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 )
{
@ -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;

View File

@ -167,91 +167,94 @@ WRITE_LINE_MEMBER(pcf8573_device::scl_w)
{
if (m_scl)
{
switch (m_state)
{
case STATE_ADDRESS:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "address %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "address %02x: write\n", m_devsel);
m_state = STATE_MODE;
}
else
{
LOGMASKED(LOG_DATA, "address %02x: read\n", m_devsel);
m_state = STATE_DATAOUT;
}
break;
case STATE_MODE:
m_mode_pointer = m_shift;
LOGMASKED(LOG_DATA, "mode pointer %02x\n", m_shift);
switch (m_mode_pointer & 0x70)
{
case 0x00: // execute address
m_address = m_mode_pointer & 0x07;
break;
case 0x10: // read control/status flags
break;
case 0x20: // reset prescaler
set_clock_register(RTC_SECOND, 0);
adjust_seconds();
break;
case 0x30: // time adjust
adjust_seconds();
break;
case 0x40: // reset NODA flag
m_status &= ~(1 << 2);
break;
case 0x50: // set NODA flag
m_status |= 1 << 2;
break;
case 0x60: // reset COMP flag
m_status &= ~(1 << 1);
m_comp_cb(0);
break;
}
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
switch (m_mode_pointer & 0x70)
{
case 0x00: // execute address
m_data[m_address] = m_shift;
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_address, m_shift);
switch (m_address)
{
case REG_HOURS: set_clock_register(RTC_HOUR, bcd_to_integer(m_data[REG_HOURS])); break;
case REG_MINUTES: set_clock_register(RTC_MINUTE, bcd_to_integer(m_data[REG_MINUTES])); break;
case REG_DAYS: set_clock_register(RTC_DAY, bcd_to_integer(m_data[REG_DAYS])); break;
case REG_MONTHS: set_clock_register(RTC_MONTH, bcd_to_integer(m_data[REG_MONTHS])); break;
}
m_address = (m_address & 0x04) | ((m_address + 1) & 0x03);
break;
}
break;
}
m_bits++;
}
else
{
if (m_bits == 8)
{
m_sdar = 0;
switch (m_state)
{
case STATE_ADDRESS:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "address %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "address %02x: write\n", m_devsel);
m_state = STATE_MODE;
}
else
{
LOGMASKED(LOG_DATA, "address %02x: read\n", m_devsel);
m_state = STATE_READSELACK;
}
break;
case STATE_MODE:
m_mode_pointer = m_shift;
LOGMASKED(LOG_DATA, "mode pointer %02x\n", m_shift);
switch (m_mode_pointer & 0x70)
{
case 0x00: // execute address
m_address = m_mode_pointer & 0x07;
break;
case 0x10: // read control/status flags
break;
case 0x20: // reset prescaler
set_clock_register(RTC_SECOND, 0);
adjust_seconds();
break;
case 0x30: // time adjust
adjust_seconds();
break;
case 0x40: // reset NODA flag
m_status &= ~(1 << 2);
break;
case 0x50: // set NODA flag
m_status |= 1 << 2;
break;
case 0x60: // reset COMP flag
m_status &= ~(1 << 1);
m_comp_cb(0);
break;
}
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
switch (m_mode_pointer & 0x70)
{
case 0x00: // execute address
m_data[m_address] = m_shift;
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_address, m_shift);
switch (m_address)
{
case REG_HOURS: set_clock_register(RTC_HOUR, bcd_to_integer(m_data[REG_HOURS])); break;
case REG_MINUTES: set_clock_register(RTC_MINUTE, bcd_to_integer(m_data[REG_MINUTES])); break;
case REG_DAYS: set_clock_register(RTC_DAY, bcd_to_integer(m_data[REG_DAYS])); break;
case REG_MONTHS: set_clock_register(RTC_MONTH, bcd_to_integer(m_data[REG_MONTHS])); break;
}
m_address = (m_address & 0x04) | ((m_address + 1) & 0x03);
break;
}
break;
}
if( m_state != STATE_IDLE )
{
m_sdar = 0 ;
}
}
else
{
@ -262,10 +265,19 @@ WRITE_LINE_MEMBER(pcf8573_device::scl_w)
}
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)
{
@ -287,7 +299,6 @@ WRITE_LINE_MEMBER(pcf8573_device::scl_w)
m_sdar = (m_shift >> 7) & 1;
m_shift = (m_shift << 1) & 0xff;
m_bits++;
}
}
else
@ -300,18 +311,11 @@ WRITE_LINE_MEMBER(pcf8573_device::scl_w)
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;

View File

@ -117,7 +117,7 @@ private:
int m_address;
int m_status;
enum { STATE_IDLE, STATE_ADDRESS, STATE_MODE, STATE_DATAIN, STATE_DATAOUT };
enum { STATE_IDLE, STATE_ADDRESS, STATE_MODE, STATE_DATAIN, STATE_DATAOUT, STATE_READSELACK };
};
// device type definition

View File

@ -242,80 +242,83 @@ WRITE_LINE_MEMBER(pcf8583_device::scl_w)
{
if (m_scl)
{
switch (m_state)
{
case STATE_DEVSEL:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_devsel);
m_state = STATE_REGISTER;
}
else
{
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_devsel);
m_state = STATE_DATAOUT;
}
break;
case STATE_REGISTER:
m_register = m_shift;
LOGMASKED(LOG_DATA, "register %02x\n", m_register);
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_register, m_shift);
m_data[m_register] = m_shift;
switch (m_register)
{
case REG_CONTROL:
if ((m_shift & 0x24) == 0x04)
logerror("Timer not implemented");
break;
case REG_SECONDS:
set_clock_register(RTC_SECOND, bcd_to_integer(m_data[REG_SECONDS]));
break;
case REG_MINUTES:
set_clock_register(RTC_MINUTE, bcd_to_integer(m_data[REG_MINUTES]));
break;
case REG_HOURS:
set_clock_register(RTC_HOUR, bcd_to_integer(m_data[REG_HOURS]));
break;
case REG_YEAR_DATE:
set_clock_register(RTC_DAY, bcd_to_integer(m_data[REG_YEAR_DATE] & 0x3f));
set_clock_register(RTC_YEAR, bcd_to_integer(m_data[REG_YEAR_DATE] >> 6));
break;
case REG_MONTH_DAY:
set_clock_register(RTC_MONTH, bcd_to_integer(m_data[REG_MONTH_DAY] & 0x1f));
set_clock_register(RTC_DAY_OF_WEEK, bcd_to_integer((m_data[REG_MONTH_DAY] >> 5) + 1));
break;
case REG_ALARM_CONTROL:
m_irq_cb(m_data[REG_ALARM_CONTROL] & 0x88 ? 1 : 0);
break;
}
m_register++;
break;
}
m_bits++;
}
else
{
if (m_bits == 8)
if( m_bits == 8 )
{
m_sdar = 0;
switch (m_state)
{
case STATE_DEVSEL:
m_devsel = m_shift;
if ((m_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_devsel);
m_state = STATE_IDLE;
}
else if ((m_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_devsel);
m_state = STATE_REGISTER;
}
else
{
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_devsel);
m_state = STATE_READSELACK;
}
break;
case STATE_REGISTER:
m_register = m_shift;
LOGMASKED(LOG_DATA, "register %02x\n", m_register);
m_state = STATE_DATAIN;
break;
case STATE_DATAIN:
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_register, m_shift);
m_data[m_register] = m_shift;
switch (m_register)
{
case REG_CONTROL:
if ((m_shift & 0x24) == 0x04)
logerror("Timer not implemented");
break;
case REG_SECONDS:
set_clock_register(RTC_SECOND, bcd_to_integer(m_data[REG_SECONDS]));
break;
case REG_MINUTES:
set_clock_register(RTC_MINUTE, bcd_to_integer(m_data[REG_MINUTES]));
break;
case REG_HOURS:
set_clock_register(RTC_HOUR, bcd_to_integer(m_data[REG_HOURS]));
break;
case REG_YEAR_DATE:
set_clock_register(RTC_DAY, bcd_to_integer(m_data[REG_YEAR_DATE] & 0x3f));
set_clock_register(RTC_YEAR, bcd_to_integer(m_data[REG_YEAR_DATE] >> 6));
break;
case REG_MONTH_DAY:
set_clock_register(RTC_MONTH, bcd_to_integer(m_data[REG_MONTH_DAY] & 0x1f));
set_clock_register(RTC_DAY_OF_WEEK, bcd_to_integer((m_data[REG_MONTH_DAY] >> 5) + 1));
break;
case REG_ALARM_CONTROL:
m_irq_cb(m_data[REG_ALARM_CONTROL] & 0x88 ? 1 : 0);
break;
}
m_register++;
break;
}
if (m_state != STATE_IDLE)
{
m_sdar = 0 ;
}
}
else
{
@ -326,10 +329,19 @@ WRITE_LINE_MEMBER(pcf8583_device::scl_w)
}
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)
{
@ -354,7 +366,6 @@ WRITE_LINE_MEMBER(pcf8583_device::scl_w)
m_sdar = (m_shift >> 7) & 1;
m_shift = (m_shift << 1) & 0xff;
m_bits++;
}
}
else
@ -367,18 +378,11 @@ WRITE_LINE_MEMBER(pcf8583_device::scl_w)
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;

View File

@ -166,7 +166,7 @@ private:
bool m_irq;
emu_timer * m_timer;
enum { STATE_IDLE, STATE_DEVSEL, STATE_REGISTER, STATE_DATAIN, STATE_DATAOUT };
enum { STATE_IDLE, STATE_DEVSEL, STATE_REGISTER, STATE_DATAIN, STATE_DATAOUT, STATE_READSELACK };
};
// device type definition

View File

@ -219,6 +219,8 @@ public:
, m_adlc(*this, "adlc")
, m_centronics(*this, "centronics")
, m_cent_data_out(*this, "cent_data_out")
, m_i2cmem(*this, "i2cmem")
, m_rtc(*this, "rtc")
{ }
void aa500(machine_config &config);
@ -238,6 +240,8 @@ private:
required_device<mc6854_device> m_adlc;
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_cent_data_out;
required_device<i2c_pcf8570_device> m_i2cmem;
required_device<pcf8573_device> m_rtc;
};
@ -326,6 +330,7 @@ class aa4000_state : public aabase_state
public:
aa4000_state(const machine_config &mconfig, device_type type, const char *tag)
: aabase_state(mconfig, type, tag)
, m_i2cmem(*this,"i2cmem")
, m_floppy(*this, "upc:fdc:%u", 0U)
//, m_test(*this, "test")
, m_ioeb_control(0)
@ -335,6 +340,8 @@ public:
void aa3020(machine_config &config);
void aa4000(machine_config &config);
required_device<pcf8583_device> m_i2cmem;
protected:
virtual void machine_reset() override;
@ -347,6 +354,7 @@ protected:
//required_device<archimedes_test_slot_device> m_test;
u8 m_ioeb_control;
};
@ -377,6 +385,7 @@ public:
aa4_state(const machine_config &mconfig, device_type type, const char *tag)
: aa5000_state(mconfig, type, tag)
, m_lc(*this, "lc")
, m_bmu(*this, "bmu")
{ }
void aa4(machine_config &config);
@ -386,6 +395,8 @@ protected:
private:
required_device<acorn_lc_device> m_lc;
required_device<acorn_bmu_device> m_bmu;
};
@ -1076,12 +1087,11 @@ void aa500_state::aa500(machine_config &config)
m_ioc->peripheral_w<5>().set(FUNC(aa500_state::peripheral5_w));
m_ioc->peripheral_r<6>().set_constant(0xff);
m_ioc->peripheral_w<6>().set(FUNC(aa500_state::peripheral6_w));
m_ioc->gpio_r<0>().set("i2cmem", FUNC(i2c_pcf8570_device::read_sda));
m_ioc->gpio_r<0>().append("rtc", FUNC(pcf8573_device::sda_r));
m_ioc->gpio_w<0>().set("i2cmem", FUNC(i2c_pcf8570_device::write_sda));
m_ioc->gpio_w<0>().append("rtc", FUNC(pcf8573_device::sda_w));
m_ioc->gpio_w<1>().set("i2cmem", FUNC(i2c_pcf8570_device::write_scl));
m_ioc->gpio_w<1>().append("rtc", FUNC(pcf8573_device::scl_w));
m_ioc->gpio_r<0>().set([this]() { return m_i2cmem->read_sda() & m_rtc->sda_r(); });
m_ioc->gpio_w<0>().set(m_i2cmem, FUNC(i2c_pcf8570_device::write_sda));
m_ioc->gpio_w<0>().append(m_rtc, FUNC(pcf8573_device::sda_w));
m_ioc->gpio_w<1>().set(m_i2cmem, FUNC(i2c_pcf8570_device::write_scl));
m_ioc->gpio_w<1>().append(m_rtc, FUNC(pcf8573_device::scl_w));
//m_ioc->gpio_r<2>().set("rtc", FUNC(pcf8573_device::min_r));
//m_ioc->gpio_r<3>().set("rtc", FUNC(pcf8573_device::sec_r));
m_ioc->gpio_r<4>().set([this] { return m_selected_floppy ? m_selected_floppy->dskchg_r() : 1; });
@ -1097,8 +1107,8 @@ void aa500_state::aa500(machine_config &config)
m_ram->set_default_size("4M");
// PCF8570 and PCF8573 (pre PCF8583)
I2C_PCF8570(config, "i2cmem");
PCF8573(config, "rtc", 32.768_kHz_XTAL);
I2C_PCF8570(config, m_i2cmem);
PCF8573(config, m_rtc, 32.768_kHz_XTAL);
FD1793(config, m_fdc, 24_MHz_XTAL / 24);
m_fdc->intrq_wr_callback().set(m_ioc, FUNC(acorn_ioc_device::fh1_w));
@ -1468,9 +1478,9 @@ void aa4000_state::aa3010(machine_config &config)
m_ioc->peripheral_w<3>().set_log("IOC: Peripheral Select 3 W");
m_ioc->peripheral_r<5>().set(FUNC(aa4000_state::ioeb_r));
m_ioc->peripheral_w<5>().set(FUNC(aa4000_state::ioeb_w));
m_ioc->gpio_r<0>().set("i2cmem", FUNC(pcf8583_device::sda_r));
m_ioc->gpio_w<0>().set("i2cmem", FUNC(pcf8583_device::sda_w));
m_ioc->gpio_w<1>().set("i2cmem", FUNC(pcf8583_device::scl_w));
m_ioc->gpio_r<0>().set(m_i2cmem, FUNC(pcf8583_device::sda_r));
m_ioc->gpio_w<0>().set(m_i2cmem, FUNC(pcf8583_device::sda_w));
m_ioc->gpio_w<1>().set(m_i2cmem, FUNC(pcf8583_device::scl_w));
m_ioc->gpio_r<2>().set_constant(1); // FDHden
m_ioc->gpio_r<3>().set("idrom", FUNC(ds2401_device::read));
m_ioc->gpio_w<3>().set("idrom", FUNC(ds2401_device::write));
@ -1479,7 +1489,7 @@ void aa4000_state::aa3010(machine_config &config)
m_ram->set_default_size("1M").set_extra_options("2M");
PCF8583(config, "i2cmem", 32.768_kHz_XTAL);
PCF8583(config, m_i2cmem, 32.768_kHz_XTAL);
DS2401(config, "idrom", 0); // DS2400
@ -1616,14 +1626,14 @@ void aa4_state::aa4(machine_config &config)
m_maincpu->set_clock(24_MHz_XTAL); // ARM3
m_maincpu->set_copro_type(arm_cpu_device::copro_type::VL86C020);
ACORN_BMU(config, "bmu", 4.194304_MHz_XTAL);
ACORN_BMU(config, m_bmu, 4.194304_MHz_XTAL);
//bmu.battlo_callback().set(m_ioc, FUNC(acorn_ioc_device::il7_w));
//m_ioc->peripheral_r<2>().set("lc", FUNC(lc_device::read));
//m_ioc->peripheral_w<2>().set("lc", FUNC(lc_device::write));
m_ioc->gpio_r<0>().append("bmu", FUNC(acorn_bmu_device::sda_r));
m_ioc->gpio_w<0>().append("bmu", FUNC(acorn_bmu_device::sda_w));
m_ioc->gpio_w<1>().append("bmu", FUNC(acorn_bmu_device::scl_w));
m_ioc->gpio_r<0>().set([this]() { return m_i2cmem->sda_r() & m_bmu->sda_r(); });
m_ioc->gpio_w<0>().append(m_bmu, FUNC(acorn_bmu_device::sda_w));
m_ioc->gpio_w<1>().append(m_bmu, FUNC(acorn_bmu_device::scl_w));
// video hardware
screen_device &screen(SCREEN(config.replace(), "screen", SCREEN_TYPE_LCD));