mirror of
https://github.com/holub/mame
synced 2025-04-16 05:24:54 +03:00
268 lines
5.0 KiB
C++
268 lines
5.0 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:Nigel Barnes
|
|
/*********************************************************************
|
|
|
|
Acorn Battery Management Unit
|
|
|
|
The BMU is actually a 4-bit Hitachi HD404304F MCU, marked as
|
|
BMU 0290032.
|
|
|
|
TODO:
|
|
- configurable status
|
|
- callback when battery low
|
|
|
|
*********************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "acorn_bmu.h"
|
|
|
|
#define LOG_DATA (1 << 1)
|
|
#define LOG_LINE (1 << 2)
|
|
|
|
#define VERBOSE (0)
|
|
#include "logmacro.h"
|
|
|
|
|
|
DEFINE_DEVICE_TYPE(ACORN_BMU, acorn_bmu_device, "acorn_bmu", "Acorn Battery Management Unit")
|
|
|
|
|
|
//**************************************************************************
|
|
// LIVE DEVICE
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// acorn_bmu_device - constructor
|
|
//-------------------------------------------------
|
|
|
|
acorn_bmu_device::acorn_bmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, ACORN_BMU, tag, owner, clock)
|
|
, m_slave_address(BMU_SLAVE_ADDRESS)
|
|
, m_scl(0)
|
|
, m_sdaw(0)
|
|
, m_sdar(1)
|
|
, m_state(STATE_IDLE)
|
|
, m_bits(0)
|
|
, m_shift(0)
|
|
, m_devsel(0)
|
|
, m_register(0)
|
|
, m_estimate(0)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------
|
|
// device_start - device-specific startup
|
|
//-------------------------------------------------
|
|
|
|
void acorn_bmu_device::device_start()
|
|
{
|
|
save_item(NAME(m_scl));
|
|
save_item(NAME(m_sdaw));
|
|
save_item(NAME(m_sdar));
|
|
save_item(NAME(m_state));
|
|
save_item(NAME(m_bits));
|
|
save_item(NAME(m_shift));
|
|
save_item(NAME(m_devsel));
|
|
save_item(NAME(m_register));
|
|
save_item(NAME(m_slave_address));
|
|
save_item(NAME(m_estimate));
|
|
}
|
|
|
|
|
|
//**************************************************************************
|
|
// READ/WRITE HANDLERS
|
|
//**************************************************************************
|
|
|
|
WRITE_LINE_MEMBER(acorn_bmu_device::scl_w)
|
|
{
|
|
if (m_scl != state)
|
|
{
|
|
m_scl = state;
|
|
LOGMASKED(LOG_LINE, "set_scl_line %d\n", m_scl);
|
|
|
|
switch (m_state)
|
|
{
|
|
case STATE_DEVSEL:
|
|
case STATE_REGISTER:
|
|
case STATE_DATAIN:
|
|
if (m_bits < 8)
|
|
{
|
|
if (m_scl)
|
|
{
|
|
m_shift = ((m_shift << 1) | m_sdaw) & 0xff;
|
|
m_bits++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_scl)
|
|
{
|
|
m_bits++;
|
|
}
|
|
else
|
|
{
|
|
if (m_bits == 8)
|
|
{
|
|
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
|
|
{
|
|
m_bits = 0;
|
|
m_sdar = 1;
|
|
}
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
switch (m_register)
|
|
{
|
|
case BMU_VERSION:
|
|
m_shift = 0x03;
|
|
break;
|
|
|
|
case BMU_STATUS:
|
|
m_shift = STATUS_CHARGER_PRESENT | STATUS_BATTERY_PRESENT | STATUS_CHARGE_STATE_KNOWN | STATUS_LID_OPEN;
|
|
break;
|
|
|
|
case BMU_CAPACITY_USED:
|
|
m_shift = 0x40;
|
|
break;
|
|
|
|
case BMU_CHARGE_ESTIMATE:
|
|
m_shift = m_estimate;
|
|
break;
|
|
|
|
case BMU_COMMAND:
|
|
m_shift = 0;
|
|
break;
|
|
}
|
|
|
|
LOGMASKED(LOG_DATA, "register[ %02x ] -> %02x\n", m_register, m_shift);
|
|
m_register++;
|
|
}
|
|
|
|
m_sdar = (m_shift >> 7) & 1;
|
|
|
|
m_shift = (m_shift << 1) & 0xff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_scl)
|
|
{
|
|
if (m_sdaw)
|
|
{
|
|
LOGMASKED(LOG_DATA, "nack\n");
|
|
m_state = STATE_IDLE;
|
|
}
|
|
|
|
m_bits = 0;
|
|
}
|
|
else
|
|
{
|
|
m_sdar = 1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(acorn_bmu_device::sda_w)
|
|
{
|
|
state &= 1;
|
|
if (m_sdaw != state)
|
|
{
|
|
LOGMASKED(LOG_LINE, "set sda %d\n", state);
|
|
m_sdaw = state;
|
|
|
|
if (m_scl)
|
|
{
|
|
if (m_sdaw)
|
|
{
|
|
LOGMASKED(LOG_DATA, "stop\n");
|
|
m_state = STATE_IDLE;
|
|
}
|
|
else
|
|
{
|
|
LOGMASKED(LOG_DATA, "start\n");
|
|
m_state = STATE_DEVSEL;
|
|
m_bits = 0;
|
|
}
|
|
|
|
m_sdar = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
READ_LINE_MEMBER(acorn_bmu_device::sda_r)
|
|
{
|
|
int res = m_sdar & 1;
|
|
|
|
LOGMASKED(LOG_LINE, "read sda %d\n", res);
|
|
|
|
return res;
|
|
}
|