// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************
Microelectronic-Marin E050-16 Real Time Clock emulation
**********************************************************************/
#include "emu.h"
#include "e0516.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define LOG 0
// states
enum
{
STATE_ADDRESS = 0,
STATE_DATA
};
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
// device type definition
const device_type E0516 = &device_creator<e0516_device>;
//-------------------------------------------------
// e0516_device - constructor
//-------------------------------------------------
e0516_device::e0516_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, E0516, "E05-16", tag, owner, clock, "e0516", __FILE__),
device_rtc_interface(mconfig, *this), m_cs(0), m_clk(0), m_data_latch(0), m_reg_latch(0), m_read_write(0), m_state(0), m_bits(0), m_dio(0), m_timer(nullptr)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void e0516_device::device_start()
{
// allocate timers
m_timer = timer_alloc();
m_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
// state saving
save_item(NAME(m_cs));
save_item(NAME(m_clk));
save_item(NAME(m_data_latch));
save_item(NAME(m_reg_latch));
save_item(NAME(m_read_write));
save_item(NAME(m_state));
save_item(NAME(m_bits));
save_item(NAME(m_dio));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void e0516_device::device_reset()
{
set_current_time(machine());
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
void e0516_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
advance_seconds();
}
//-------------------------------------------------
// cs_w - chip select input
//-------------------------------------------------
WRITE_LINE_MEMBER( e0516_device::cs_w )
{
if (LOG) logerror("E05-16 '%s' CS %u\n", tag(), state);
m_cs = state;
if (m_cs)
{
m_data_latch = 0;
m_reg_latch = 0;
m_bits = 0;
m_state = STATE_ADDRESS;
}
}
//-------------------------------------------------
// clk_w - serial clock input
//-------------------------------------------------
WRITE_LINE_MEMBER( e0516_device::clk_w )
{
if (LOG) logerror("E05-16 '%s' CLK %u\n", tag(), state);
m_clk = state;
if (m_cs || m_clk) return;
m_bits++;
if (m_state == STATE_ADDRESS)
{
if (LOG) logerror("E05-16 '%s' Command Bit %u\n", tag(), m_dio);
// command
m_reg_latch |= m_dio << 3;
m_reg_latch >>= 1;
if (m_bits == 4)
{
m_state = STATE_DATA;
m_bits = 0;
if (BIT(m_reg_latch, 0))
{
// load register value to data latch
m_data_latch = convert_to_bcd(get_clock_register(m_reg_latch >> 1));
}
}
}
else
{
// data
if (BIT(m_reg_latch, 0))
{
// read
if (LOG) logerror("E05-16 '%s' Data Bit OUT %u\n", tag(), m_dio);
m_dio = BIT(m_data_latch, 0);
m_data_latch >>= 1;
}
else
{
// write
if (LOG) logerror("E05-16 '%s' Data Bit IN %u\n", tag(), m_dio);
m_data_latch |= m_dio << 7;
m_data_latch >>= 1;
}
if (m_bits == 8)
{
m_state = STATE_ADDRESS;
m_bits = 0;
if (!BIT(m_reg_latch, 0))
{
// write latched data to register
set_clock_register(m_reg_latch >> 1, bcd_to_integer(m_data_latch));
}
}
}
}
//-------------------------------------------------
// dio_w - serial data input
//-------------------------------------------------
WRITE_LINE_MEMBER( e0516_device::dio_w )
{
if (LOG) logerror("E05-16 '%s' DIO %u\n", tag(), state);
m_dio = state;
}
//-------------------------------------------------
// do_r - serial data output
//-------------------------------------------------
READ_LINE_MEMBER( e0516_device::dio_r )
{
return m_dio;
}