mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Converted MSM58321 to DEVCB2, uses level logic rather than edge detection for strobes (as per datasheet), added nvram interface as there are some configuration bits to save, added support for 12 and 24 hour. It defaults to 12 hour, but you can configure it in the driver to default to 24H. You can configure what year 0 is in the driver, which is used when setting the date at startup. [smf]
This commit is contained in:
parent
ffc7a1c776
commit
4830ec15d8
@ -13,11 +13,11 @@
|
||||
|
||||
TODO:
|
||||
|
||||
- 12/24 hour
|
||||
- AM/PM
|
||||
- leap year
|
||||
- stop
|
||||
- test
|
||||
- reset
|
||||
- busy
|
||||
- reference registers
|
||||
|
||||
*/
|
||||
@ -57,6 +57,36 @@ enum
|
||||
REGISTER_REF1
|
||||
};
|
||||
|
||||
static const char *reg_name(UINT8 address)
|
||||
{
|
||||
switch(address)
|
||||
{
|
||||
case REGISTER_S1: return "S1";
|
||||
case REGISTER_S10: return "S10";
|
||||
case REGISTER_MI1: return "MI1";
|
||||
case REGISTER_MI10: return "MI10";
|
||||
case REGISTER_H1: return "H1";
|
||||
case REGISTER_H10: return "H10";
|
||||
case REGISTER_W: return "W";
|
||||
case REGISTER_D1: return "D1";
|
||||
case REGISTER_D10: return "D10";
|
||||
case REGISTER_MO1: return "MO1";
|
||||
case REGISTER_MO10: return "MO10";
|
||||
case REGISTER_Y1: return "Y1";
|
||||
case REGISTER_Y10: return "Y10";
|
||||
case REGISTER_RESET: return "RESET";
|
||||
case REGISTER_REF0: return "REF0";
|
||||
case REGISTER_REF1: return "REF1";
|
||||
}
|
||||
|
||||
return "INVALID REGISTER";
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
H10_PM = 4,
|
||||
H10_24 = 8
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -69,7 +99,39 @@ enum
|
||||
|
||||
inline int msm58321_device::read_counter(int counter)
|
||||
{
|
||||
return (m_reg[counter + 1] * 10) + m_reg[counter];
|
||||
int data = m_reg[counter];
|
||||
|
||||
if (counter == REGISTER_H1)
|
||||
{
|
||||
int h10 = m_reg[REGISTER_H10];
|
||||
|
||||
if (h10 & H10_24)
|
||||
{
|
||||
data += (h10 & 3) * 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
data += (h10 & 1) * 10;
|
||||
|
||||
if (h10 & H10_PM)
|
||||
{
|
||||
if (data != 12)
|
||||
{
|
||||
data += 12;
|
||||
}
|
||||
}
|
||||
else if (data == 12)
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data += (m_reg[counter + 1] * 10);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@ -77,18 +139,40 @@ inline int msm58321_device::read_counter(int counter)
|
||||
// write_counter -
|
||||
//-------------------------------------------------
|
||||
|
||||
inline void msm58321_device::write_counter(int counter, int value)
|
||||
inline void msm58321_device::write_counter(int address, int data)
|
||||
{
|
||||
m_reg[counter] = value % 10;
|
||||
m_reg[counter + 1] = value / 10;
|
||||
int flag = 0;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case REGISTER_H1:
|
||||
flag = m_reg[REGISTER_H10] & H10_24;
|
||||
if (!flag)
|
||||
{
|
||||
if (data >= 12)
|
||||
{
|
||||
data -= 12;
|
||||
flag = H10_PM;
|
||||
}
|
||||
|
||||
if (data == 0)
|
||||
{
|
||||
data = 12;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REGISTER_D1:
|
||||
flag = (m_reg[REGISTER_D10] & ~3);
|
||||
break;
|
||||
}
|
||||
|
||||
m_reg[address] = data % 10;
|
||||
m_reg[address + 1] = (data / 10) | flag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// msm58321_device - constructor
|
||||
//-------------------------------------------------
|
||||
@ -96,31 +180,30 @@ inline void msm58321_device::write_counter(int counter, int value)
|
||||
msm58321_device::msm58321_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, MSM58321, "MSM58321", tag, owner, clock, "msm58321", __FILE__),
|
||||
device_rtc_interface(mconfig, *this),
|
||||
m_cs2(0)
|
||||
device_nvram_interface(mconfig, *this),
|
||||
m_d0_handler(*this),
|
||||
m_d1_handler(*this),
|
||||
m_d2_handler(*this),
|
||||
m_d3_handler(*this),
|
||||
m_busy_handler(*this),
|
||||
m_cs2(0),
|
||||
m_write(0),
|
||||
m_read(0),
|
||||
m_d0_in(0),
|
||||
m_d0_out(0),
|
||||
m_d1_in(0),
|
||||
m_d1_out(0),
|
||||
m_d2_in(0),
|
||||
m_d2_out(0),
|
||||
m_d3_in(0),
|
||||
m_d3_out(0),
|
||||
m_address_write(0),
|
||||
m_busy(0),
|
||||
m_stop(0),
|
||||
m_test(0),
|
||||
m_cs1(0),
|
||||
m_address(0xf)
|
||||
{
|
||||
for (int i = 0; i < 13; i++)
|
||||
m_reg[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void msm58321_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const msm58321_interface *intf = reinterpret_cast<const msm58321_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<msm58321_interface *>(this) = *intf;
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&m_out_busy_cb, 0, sizeof(m_out_busy_cb));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -131,7 +214,11 @@ void msm58321_device::device_config_complete()
|
||||
void msm58321_device::device_start()
|
||||
{
|
||||
// resolve callbacks
|
||||
m_out_busy_func.resolve(m_out_busy_cb, *this);
|
||||
m_d0_handler.resolve_safe();
|
||||
m_d1_handler.resolve_safe();
|
||||
m_d2_handler.resolve_safe();
|
||||
m_d3_handler.resolve_safe();
|
||||
m_busy_handler.resolve_safe();
|
||||
|
||||
// allocate timers
|
||||
m_clock_timer = timer_alloc(TIMER_CLOCK);
|
||||
@ -141,25 +228,28 @@ void msm58321_device::device_start()
|
||||
m_busy_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
|
||||
|
||||
// state saving
|
||||
save_item(NAME(m_cs1));
|
||||
save_item(NAME(m_cs2));
|
||||
save_item(NAME(m_busy));
|
||||
save_item(NAME(m_read));
|
||||
save_item(NAME(m_write));
|
||||
save_item(NAME(m_read));
|
||||
save_item(NAME(m_d0_in));
|
||||
save_item(NAME(m_d0_out));
|
||||
save_item(NAME(m_d1_in));
|
||||
save_item(NAME(m_d1_out));
|
||||
save_item(NAME(m_d2_in));
|
||||
save_item(NAME(m_d2_out));
|
||||
save_item(NAME(m_d3_in));
|
||||
save_item(NAME(m_d3_out));
|
||||
save_item(NAME(m_address_write));
|
||||
save_item(NAME(m_reg));
|
||||
save_item(NAME(m_latch));
|
||||
save_item(NAME(m_busy));
|
||||
save_item(NAME(m_stop));
|
||||
save_item(NAME(m_test));
|
||||
save_item(NAME(m_cs1));
|
||||
save_item(NAME(m_address));
|
||||
}
|
||||
save_item(NAME(m_reg));
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void msm58321_device::device_reset()
|
||||
{
|
||||
set_current_time(machine());
|
||||
|
||||
update_output();
|
||||
}
|
||||
|
||||
|
||||
@ -176,8 +266,8 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
||||
break;
|
||||
|
||||
case TIMER_BUSY:
|
||||
m_out_busy_func(m_busy);
|
||||
m_busy = !m_busy;
|
||||
m_busy_handler(m_busy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -189,75 +279,133 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
||||
|
||||
void msm58321_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
write_counter(REGISTER_Y1, year);
|
||||
write_counter(REGISTER_Y1, (year - m_year0) % 100);
|
||||
write_counter(REGISTER_MO1, month);
|
||||
write_counter(REGISTER_D1, day);
|
||||
m_reg[REGISTER_W] = day_of_week;
|
||||
write_counter(REGISTER_H1, hour);
|
||||
write_counter(REGISTER_MI1, minute);
|
||||
write_counter(REGISTER_S1, second);
|
||||
|
||||
update_output();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_default - called to initialize NVRAM to
|
||||
// its default state
|
||||
//-------------------------------------------------
|
||||
|
||||
void msm58321_device::nvram_default()
|
||||
{
|
||||
for (int i = 0; i < 13; i++)
|
||||
m_reg[i] = 0;
|
||||
|
||||
if (m_default_24h)
|
||||
m_reg[REGISTER_H10] = H10_24;
|
||||
|
||||
clock_updated();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read -
|
||||
// nvram_read - called to read NVRAM from the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
READ8_MEMBER( msm58321_device::read )
|
||||
void msm58321_device::nvram_read(emu_file &file)
|
||||
{
|
||||
UINT8 data = 0;
|
||||
file.read(m_reg, sizeof(m_reg));
|
||||
|
||||
if (m_cs1 && m_cs2)
|
||||
clock_updated();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_write - called to write NVRAM to the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void msm58321_device::nvram_write(emu_file &file)
|
||||
{
|
||||
if (m_read)
|
||||
file.write(m_reg, sizeof(m_reg));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// update_output -
|
||||
//-------------------------------------------------
|
||||
|
||||
void msm58321_device::update_output()
|
||||
{
|
||||
UINT8 data = 0xf;
|
||||
|
||||
if (m_cs1 && m_cs2 && m_read)
|
||||
{
|
||||
switch (m_address)
|
||||
{
|
||||
case REGISTER_RESET:
|
||||
data = 0;
|
||||
break;
|
||||
|
||||
case REGISTER_REF0:
|
||||
case REGISTER_REF1:
|
||||
// TODO: output reference values
|
||||
data = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
data = m_reg[m_address];
|
||||
break;
|
||||
}
|
||||
|
||||
if (LOG) logerror("MSM58321 '%s' Register Read %s (%01x): %01x\n", tag(), reg_name(m_address), m_address, data & 0x0f);
|
||||
}
|
||||
|
||||
if (m_write)
|
||||
int d0 = (data >> 0) & 1;
|
||||
if (m_d0_out != d0)
|
||||
{
|
||||
if (m_address >= REGISTER_REF0)
|
||||
m_d0_out = d0;
|
||||
m_d0_handler(d0);
|
||||
}
|
||||
|
||||
int d1 = (data >> 1) & 1;
|
||||
if (m_d1_out != d1)
|
||||
{
|
||||
// TODO: output reference values
|
||||
}
|
||||
}
|
||||
m_d1_out = d1;
|
||||
m_d1_handler(d1);
|
||||
}
|
||||
|
||||
if (LOG) logerror("MSM58321 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
|
||||
int d2 = (data >> 2) & 1;
|
||||
if (m_d2_out != d2)
|
||||
{
|
||||
m_d2_out = d2;
|
||||
m_d2_handler(d2);
|
||||
}
|
||||
|
||||
return data;
|
||||
int d3 = (data >> 3) & 1;
|
||||
if (m_d3_out != d3)
|
||||
{
|
||||
m_d3_out = d3;
|
||||
m_d3_handler(d3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write -
|
||||
// update_input() -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER( msm58321_device::write )
|
||||
void msm58321_device::update_input()
|
||||
{
|
||||
// latch data for future use
|
||||
m_latch = data & 0x0f;
|
||||
|
||||
if (!m_cs1 || !m_cs2) return;
|
||||
if (m_cs1 && m_cs2)
|
||||
{
|
||||
UINT8 data = m_d0_in | (m_d1_in << 1) | (m_d2_in << 2) | (m_d3_in << 3);
|
||||
|
||||
if (m_address_write)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
|
||||
if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), data);
|
||||
|
||||
// latch address
|
||||
m_address = m_latch;
|
||||
m_address = data;
|
||||
}
|
||||
|
||||
if (m_write)
|
||||
@ -274,50 +422,60 @@ WRITE8_MEMBER( msm58321_device::write )
|
||||
break;
|
||||
|
||||
default:
|
||||
if (LOG) logerror("MSM58321 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
|
||||
m_reg[m_address] = m_latch & 0x0f;
|
||||
if (LOG) logerror("MSM58321 '%s' Register Write %s (%01x): %01x\n", tag(), reg_name(m_address), m_address, data);
|
||||
|
||||
set_time(false, read_counter(REGISTER_Y1), read_counter(REGISTER_MO1), read_counter(REGISTER_D1), m_reg[REGISTER_W],
|
||||
switch (m_address)
|
||||
{
|
||||
case REGISTER_S10:
|
||||
case REGISTER_MI10:
|
||||
case REGISTER_W:
|
||||
m_reg[m_address] = data & 7;
|
||||
break;
|
||||
|
||||
case REGISTER_H10:
|
||||
if (data & H10_24)
|
||||
{
|
||||
// "When D3 = 1 is written, the D2 bit is reset inside the IC."
|
||||
// but it doesn't say if this is done immediately or on the next update
|
||||
m_reg[m_address] = data & ~H10_PM;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reg[m_address] = data;
|
||||
}
|
||||
break;
|
||||
|
||||
case REGISTER_MO10:
|
||||
m_reg[m_address] = data & 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
m_reg[m_address] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
set_time(false, read_counter(REGISTER_Y1) + m_year0, read_counter(REGISTER_MO1), read_counter(REGISTER_D1), m_reg[REGISTER_W],
|
||||
read_counter(REGISTER_H1), read_counter(REGISTER_MI1), read_counter(REGISTER_S1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// cs1_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::cs1_w )
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' CS1: %u\n", tag(), state);
|
||||
|
||||
m_cs1 = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// cs2_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::cs2_w )
|
||||
{
|
||||
if (m_cs2 != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' CS2: %u\n", tag(), state);
|
||||
|
||||
m_cs2 = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::read_w )
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' READ: %u\n", tag(), state);
|
||||
|
||||
m_read = state;
|
||||
}
|
||||
|
||||
|
||||
@ -326,10 +484,93 @@ WRITE_LINE_MEMBER( msm58321_device::read_w )
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::write_w )
|
||||
{
|
||||
if (m_write != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' WRITE: %u\n", tag(), state);
|
||||
|
||||
m_write = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::read_w )
|
||||
{
|
||||
if (m_read != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' READ: %u\n", tag(), state);
|
||||
|
||||
m_read = state;
|
||||
|
||||
update_output();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// d0_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::d0_w )
|
||||
{
|
||||
if (m_d0_in != state)
|
||||
{
|
||||
m_d0_in = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// d1_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::d1_w )
|
||||
{
|
||||
if (m_d1_in != state)
|
||||
{
|
||||
m_d1_in = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// d2_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::d2_w )
|
||||
{
|
||||
if (m_d2_in != state)
|
||||
{
|
||||
m_d2_in = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// d3_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::d3_w )
|
||||
{
|
||||
if (m_d3_in != state)
|
||||
{
|
||||
m_d3_in = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -338,17 +579,14 @@ WRITE_LINE_MEMBER( msm58321_device::write_w )
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::address_write_w )
|
||||
{
|
||||
if (m_address_write != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' ADDRESS WRITE: %u\n", tag(), state);
|
||||
|
||||
m_address_write = state;
|
||||
|
||||
if (m_address_write)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
|
||||
|
||||
// latch address
|
||||
m_address = m_latch;
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,8 +596,13 @@ WRITE_LINE_MEMBER( msm58321_device::address_write_w )
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::stop_w )
|
||||
{
|
||||
if (m_stop != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' STOP: %u\n", tag(), state);
|
||||
|
||||
m_stop = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -369,15 +612,28 @@ WRITE_LINE_MEMBER( msm58321_device::stop_w )
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::test_w )
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' TEST: %u\n", tag(), state);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// busy_r -
|
||||
//-------------------------------------------------
|
||||
|
||||
READ_LINE_MEMBER( msm58321_device::busy_r )
|
||||
if (m_test != state)
|
||||
{
|
||||
return m_busy;
|
||||
if (LOG) logerror("MSM58321 '%s' TEST: %u\n", tag(), state);
|
||||
|
||||
m_test = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// cs1_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( msm58321_device::cs1_w )
|
||||
{
|
||||
if (m_cs1 != state)
|
||||
{
|
||||
if (LOG) logerror("MSM58321 '%s' CS1: %u\n", tag(), state);
|
||||
|
||||
m_cs1 = state;
|
||||
|
||||
update_input();
|
||||
}
|
||||
}
|
||||
|
@ -33,79 +33,109 @@
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_MSM58321_ADD(_tag, _clock, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, MSM58321, _clock) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
#define MCFG_MSM58321_D0_HANDLER(_devcb) \
|
||||
devcb = &msm58321_device::set_d0_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
#define MSM58321_INTERFACE(name) \
|
||||
const msm58321_interface (name) =
|
||||
#define MCFG_MSM58321_D1_HANDLER(_devcb) \
|
||||
devcb = &msm58321_device::set_d1_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
#define MCFG_MSM58321_D2_HANDLER(_devcb) \
|
||||
devcb = &msm58321_device::set_d2_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
#define MCFG_MSM58321_D3_HANDLER(_devcb) \
|
||||
devcb = &msm58321_device::set_d3_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> msm58321_interface
|
||||
|
||||
struct msm58321_interface
|
||||
{
|
||||
devcb_write_line m_out_busy_cb;
|
||||
};
|
||||
#define MCFG_MSM58321_BUSY_HANDLER(_devcb) \
|
||||
devcb = &msm58321_device::set_busy_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
#define MCFG_MSM58321_YEAR0(_year0) \
|
||||
msm58321_device::set_year0(*device, _year0);
|
||||
|
||||
#define MCFG_MSM58321_DEFAULT_24H(_default_24h) \
|
||||
msm58321_device::set_default_24h(*device, _default_24h);
|
||||
|
||||
// ======================> msm58321_device
|
||||
|
||||
class msm58321_device : public device_t,
|
||||
public device_rtc_interface,
|
||||
public msm58321_interface
|
||||
public device_nvram_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
msm58321_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_READ8_MEMBER( read );
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb2_base &set_d0_handler(device_t &device, _Object object) { return downcast<msm58321_device &>(device).m_d0_handler.set_callback(object); }
|
||||
template<class _Object> static devcb2_base &set_d1_handler(device_t &device, _Object object) { return downcast<msm58321_device &>(device).m_d1_handler.set_callback(object); }
|
||||
template<class _Object> static devcb2_base &set_d2_handler(device_t &device, _Object object) { return downcast<msm58321_device &>(device).m_d2_handler.set_callback(object); }
|
||||
template<class _Object> static devcb2_base &set_d3_handler(device_t &device, _Object object) { return downcast<msm58321_device &>(device).m_d3_handler.set_callback(object); }
|
||||
template<class _Object> static devcb2_base &set_busy_handler(device_t &device, _Object object) { return downcast<msm58321_device &>(device).m_busy_handler.set_callback(object); }
|
||||
static void set_year0(device_t &device, int year0) { downcast<msm58321_device &>(device).m_year0 = year0; }
|
||||
static void set_default_24h(device_t &device, bool default_24h) { downcast<msm58321_device &>(device).m_default_24h = default_24h; }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( cs1_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( cs2_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( read_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( write_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( read_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( d0_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( d1_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( d2_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( d3_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( address_write_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( stop_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( test_w );
|
||||
DECLARE_READ_LINE_MEMBER( busy_r );
|
||||
DECLARE_WRITE_LINE_MEMBER( cs1_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
// device_rtc_interface overrides
|
||||
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
|
||||
virtual bool rtc_feature_y2k() { return m_year0 != 0; }
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_default();
|
||||
virtual void nvram_read(emu_file &file);
|
||||
virtual void nvram_write(emu_file &file);
|
||||
|
||||
private:
|
||||
static const device_timer_id TIMER_CLOCK = 0;
|
||||
static const device_timer_id TIMER_BUSY = 1;
|
||||
|
||||
void update_input();
|
||||
void update_output();
|
||||
|
||||
inline int read_counter(int counter);
|
||||
inline void write_counter(int counter, int value);
|
||||
|
||||
devcb_resolved_write_line m_out_busy_func;
|
||||
int m_year0;
|
||||
bool m_default_24h;
|
||||
devcb2_write_line m_d0_handler;
|
||||
devcb2_write_line m_d1_handler;
|
||||
devcb2_write_line m_d2_handler;
|
||||
devcb2_write_line m_d3_handler;
|
||||
devcb2_write_line m_busy_handler;
|
||||
|
||||
int m_cs1; // chip select 1
|
||||
int m_cs2; // chip select 2
|
||||
int m_busy; // busy flag
|
||||
int m_read; // read data
|
||||
int m_write; // write data
|
||||
int m_read; // read data
|
||||
int m_d0_in; // d0
|
||||
int m_d0_out; // d0
|
||||
int m_d1_in; // d1
|
||||
int m_d1_out; // d1
|
||||
int m_d2_in; // d2
|
||||
int m_d2_out; // d2
|
||||
int m_d3_in; // d3
|
||||
int m_d3_out; // d3
|
||||
int m_address_write; // write address
|
||||
int m_busy; // busy flag
|
||||
int m_stop; // stop flag
|
||||
int m_test; // test flag
|
||||
int m_cs1; // chip select 1
|
||||
|
||||
UINT8 m_reg[13]; // registers
|
||||
UINT8 m_latch; // data latch (not present in real chip)
|
||||
UINT8 m_address; // address latch
|
||||
UINT8 m_reg[13]; // registers
|
||||
|
||||
// timers
|
||||
emu_timer *m_clock_timer;
|
||||
@ -116,6 +146,4 @@ private:
|
||||
// device type definition
|
||||
extern const device_type MSM58321;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -71,7 +71,10 @@ public:
|
||||
m_rtc(*this, "rtc"),
|
||||
m_palram(*this, "palram"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_beeper(*this, "beeper") { }
|
||||
m_beeper(*this, "beeper"),
|
||||
m_rtc_portc(0)
|
||||
{
|
||||
}
|
||||
|
||||
required_device<msm58321_device> m_rtc;
|
||||
required_shared_ptr<UINT16> m_palram;
|
||||
@ -94,6 +97,8 @@ public:
|
||||
DECLARE_WRITE8_MEMBER(upper_mask_w);
|
||||
DECLARE_WRITE8_MEMBER(crtc_bank_w);
|
||||
DECLARE_WRITE8_MEMBER(rtc_porta_w);
|
||||
DECLARE_READ8_MEMBER(rtc_portc_r);
|
||||
DECLARE_WRITE8_MEMBER(rtc_portc_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(pc100_set_int_line);
|
||||
UINT16 *m_kanji_rom;
|
||||
UINT16 *m_vram;
|
||||
@ -121,6 +126,12 @@ public:
|
||||
IRQ_CALLBACK_MEMBER(pc100_irq_callback);
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<beep_device> m_beeper;
|
||||
|
||||
WRITE_LINE_MEMBER(rtc_portc_0_w) { m_rtc_portc = (m_rtc_portc & ~(1 << 0)) | ((state & 1) << 0); }
|
||||
WRITE_LINE_MEMBER(rtc_portc_1_w) { m_rtc_portc = (m_rtc_portc & ~(1 << 1)) | ((state & 1) << 1); }
|
||||
WRITE_LINE_MEMBER(rtc_portc_2_w) { m_rtc_portc = (m_rtc_portc & ~(1 << 2)) | ((state & 1) << 2); }
|
||||
WRITE_LINE_MEMBER(rtc_portc_3_w) { m_rtc_portc = (m_rtc_portc & ~(1 << 3)) | ((state & 1) << 3); }
|
||||
UINT8 m_rtc_portc;
|
||||
};
|
||||
|
||||
void pc100_state::video_start()
|
||||
@ -363,9 +374,22 @@ WRITE8_MEMBER( pc100_state::rtc_porta_w )
|
||||
---- ---x write
|
||||
*/
|
||||
|
||||
m_rtc->write_w(data & 1);
|
||||
m_rtc->read_w((data & 2) >> 1);
|
||||
m_rtc->cs1_w((data & 4) >> 2);
|
||||
m_rtc->write_w((data >> 0) & 1);
|
||||
m_rtc->read_w((data >> 1) & 1);
|
||||
m_rtc->cs1_w((data >> 2) & 1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( pc100_state::rtc_portc_w )
|
||||
{
|
||||
m_rtc->d0_w((data >> 0) & 1);
|
||||
m_rtc->d1_w((data >> 1) & 1);
|
||||
m_rtc->d2_w((data >> 2) & 1);
|
||||
m_rtc->d3_w((data >> 3) & 1);
|
||||
}
|
||||
|
||||
READ8_MEMBER( pc100_state::rtc_portc_r )
|
||||
{
|
||||
return m_rtc_portc;
|
||||
}
|
||||
|
||||
static I8255A_INTERFACE( pc100_ppi8255_interface_1 )
|
||||
@ -374,8 +398,8 @@ static I8255A_INTERFACE( pc100_ppi8255_interface_1 )
|
||||
DEVCB_DRIVER_MEMBER(pc100_state, rtc_porta_w),
|
||||
DEVCB_NULL,
|
||||
DEVCB_NULL,
|
||||
DEVCB_DEVICE_MEMBER("rtc", msm58321_device, read),
|
||||
DEVCB_DEVICE_MEMBER("rtc", msm58321_device, write)
|
||||
DEVCB_DRIVER_MEMBER(pc100_state, rtc_portc_r),
|
||||
DEVCB_DRIVER_MEMBER(pc100_state, rtc_portc_w)
|
||||
};
|
||||
|
||||
|
||||
@ -475,11 +499,6 @@ static SLOT_INTERFACE_START( pc100_floppies )
|
||||
SLOT_INTERFACE( "525hd", FLOPPY_525_HD )
|
||||
SLOT_INTERFACE_END
|
||||
|
||||
static MSM58321_INTERFACE( rtc_intf )
|
||||
{
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
#define MASTER_CLOCK 6988800
|
||||
|
||||
static MACHINE_CONFIG_START( pc100, pc100_state )
|
||||
@ -497,7 +516,12 @@ static MACHINE_CONFIG_START( pc100, pc100_state )
|
||||
MCFG_I8255_ADD( "ppi8255_2", pc100_ppi8255_interface_2 )
|
||||
MCFG_PIC8259_ADD( "pic8259", WRITELINE(pc100_state, pc100_set_int_line), GND, NULL )
|
||||
MCFG_UPD765A_ADD("upd765", true, true)
|
||||
MCFG_MSM58321_ADD("rtc", XTAL_32_768kHz, rtc_intf)
|
||||
|
||||
MCFG_DEVICE_ADD("rtc", MSM58321, XTAL_32_768kHz)
|
||||
MCFG_MSM58321_D0_HANDLER(WRITELINE(pc100_state, rtc_portc_0_w))
|
||||
MCFG_MSM58321_D1_HANDLER(WRITELINE(pc100_state, rtc_portc_1_w))
|
||||
MCFG_MSM58321_D2_HANDLER(WRITELINE(pc100_state, rtc_portc_2_w))
|
||||
MCFG_MSM58321_D3_HANDLER(WRITELINE(pc100_state, rtc_portc_3_w))
|
||||
|
||||
MCFG_FLOPPY_DRIVE_ADD("upd765:0", pc100_floppies, "525hd", floppy_image_device::default_floppy_formats)
|
||||
MCFG_FLOPPY_DRIVE_ADD("upd765:1", pc100_floppies, "525hd", floppy_image_device::default_floppy_formats)
|
||||
|
@ -671,13 +671,6 @@ static I8214_INTERFACE( pic_intf )
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
// MSM58321 Interface
|
||||
|
||||
static MSM58321_INTERFACE( rtc_intf )
|
||||
{
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
// Display 8255A Interface
|
||||
|
||||
WRITE8_MEMBER(v1050_state::disp_ppi_pc_w)
|
||||
@ -864,6 +857,19 @@ WRITE8_MEMBER( v1050_state::rtc_ppi_pb_w )
|
||||
m_int_mask = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER( v1050_state::rtc_ppi_pa_r )
|
||||
{
|
||||
return m_rtc_ppi_pa;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( v1050_state::rtc_ppi_pa_w )
|
||||
{
|
||||
m_rtc->d0_w((data >> 0) & 1);
|
||||
m_rtc->d1_w((data >> 1) & 1);
|
||||
m_rtc->d2_w((data >> 2) & 1);
|
||||
m_rtc->d3_w((data >> 3) & 1);
|
||||
}
|
||||
|
||||
READ8_MEMBER( v1050_state::rtc_ppi_pc_r )
|
||||
{
|
||||
/*
|
||||
@ -881,7 +887,7 @@ READ8_MEMBER( v1050_state::rtc_ppi_pc_r )
|
||||
|
||||
*/
|
||||
|
||||
return m_rtc->busy_r() << 3;
|
||||
return m_rtc_ppi_pc;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( v1050_state::rtc_ppi_pc_w )
|
||||
@ -909,8 +915,8 @@ WRITE8_MEMBER( v1050_state::rtc_ppi_pc_w )
|
||||
|
||||
static I8255A_INTERFACE( rtc_ppi_intf )
|
||||
{
|
||||
DEVCB_DEVICE_MEMBER(MSM58321RS_TAG, msm58321_device, read),
|
||||
DEVCB_DEVICE_MEMBER(MSM58321RS_TAG, msm58321_device, write),
|
||||
DEVCB_DRIVER_MEMBER(v1050_state, rtc_ppi_pa_r),
|
||||
DEVCB_DRIVER_MEMBER(v1050_state, rtc_ppi_pa_w),
|
||||
DEVCB_NULL,
|
||||
DEVCB_DRIVER_MEMBER(v1050_state, rtc_ppi_pb_w),
|
||||
DEVCB_DRIVER_MEMBER(v1050_state, rtc_ppi_pc_r),
|
||||
@ -1119,7 +1125,14 @@ static MACHINE_CONFIG_START( v1050, v1050_state )
|
||||
|
||||
// devices
|
||||
MCFG_I8214_ADD(UPB8214_TAG, XTAL_16MHz/4, pic_intf)
|
||||
MCFG_MSM58321_ADD(MSM58321RS_TAG, XTAL_32_768kHz, rtc_intf)
|
||||
|
||||
MCFG_DEVICE_ADD(MSM58321RS_TAG, MSM58321, XTAL_32_768kHz)
|
||||
MCFG_MSM58321_D0_HANDLER(WRITELINE(v1050_state, rtc_ppi_pa_0_w))
|
||||
MCFG_MSM58321_D1_HANDLER(WRITELINE(v1050_state, rtc_ppi_pa_1_w))
|
||||
MCFG_MSM58321_D2_HANDLER(WRITELINE(v1050_state, rtc_ppi_pa_2_w))
|
||||
MCFG_MSM58321_D3_HANDLER(WRITELINE(v1050_state, rtc_ppi_pa_3_w))
|
||||
MCFG_MSM58321_BUSY_HANDLER(WRITELINE(v1050_state, rtc_ppi_pc_3_w))
|
||||
|
||||
MCFG_I8255A_ADD(I8255A_DISP_TAG, disp_ppi_intf)
|
||||
MCFG_I8255A_ADD(I8255A_MISC_TAG, misc_ppi_intf)
|
||||
MCFG_I8255A_ADD(I8255A_RTC_TAG, rtc_ppi_intf)
|
||||
|
@ -85,8 +85,11 @@ public:
|
||||
m_sasibus(*this, SASIBUS_TAG ":host"),
|
||||
m_rom(*this, Z80_TAG),
|
||||
m_video_ram(*this, "video_ram"),
|
||||
m_attr_ram(*this, "attr_ram")
|
||||
{ }
|
||||
m_attr_ram(*this, "attr_ram"),
|
||||
m_rtc_ppi_pa(0),
|
||||
m_rtc_ppi_pc(0)
|
||||
{
|
||||
}
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_subcpu;
|
||||
@ -130,6 +133,8 @@ public:
|
||||
DECLARE_WRITE8_MEMBER( p2_w );
|
||||
DECLARE_WRITE8_MEMBER( misc_ppi_pa_w );
|
||||
DECLARE_WRITE8_MEMBER( misc_ppi_pc_w );
|
||||
DECLARE_READ8_MEMBER( rtc_ppi_pa_r );
|
||||
DECLARE_WRITE8_MEMBER( rtc_ppi_pa_w );
|
||||
DECLARE_WRITE8_MEMBER( rtc_ppi_pb_w );
|
||||
DECLARE_READ8_MEMBER( rtc_ppi_pc_r );
|
||||
DECLARE_WRITE8_MEMBER( rtc_ppi_pc_w );
|
||||
@ -148,6 +153,14 @@ public:
|
||||
DECLARE_READ8_MEMBER( sasi_status_r );
|
||||
DECLARE_WRITE8_MEMBER( sasi_ctrl_w );
|
||||
|
||||
WRITE_LINE_MEMBER( rtc_ppi_pa_0_w ){ m_rtc_ppi_pa = (m_rtc_ppi_pa & ~(1 << 0)) | ((state & 1) << 0); }
|
||||
WRITE_LINE_MEMBER( rtc_ppi_pa_1_w ){ m_rtc_ppi_pa = (m_rtc_ppi_pa & ~(1 << 1)) | ((state & 1) << 1); }
|
||||
WRITE_LINE_MEMBER( rtc_ppi_pa_2_w ){ m_rtc_ppi_pa = (m_rtc_ppi_pa & ~(1 << 2)) | ((state & 1) << 2); }
|
||||
WRITE_LINE_MEMBER( rtc_ppi_pa_3_w ){ m_rtc_ppi_pa = (m_rtc_ppi_pa & ~(1 << 3)) | ((state & 1) << 3); }
|
||||
UINT8 m_rtc_ppi_pa;
|
||||
WRITE_LINE_MEMBER( rtc_ppi_pc_3_w ){ m_rtc_ppi_pc = (m_rtc_ppi_pc & ~(1 << 3)) | ((state & 1) << 3); }
|
||||
UINT8 m_rtc_ppi_pc;
|
||||
|
||||
void bankswitch();
|
||||
void update_fdc();
|
||||
void set_interrupt(UINT8 mask, int state);
|
||||
|
Loading…
Reference in New Issue
Block a user