mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
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:
parent
508383295d
commit
4cb71c31d2
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user