mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
upd1990/4990 improvements, most notably added serial command input
This commit is contained in:
parent
22556b3d67
commit
bf2db1521e
@ -12,9 +12,8 @@
|
||||
/*
|
||||
|
||||
TODO:
|
||||
|
||||
- set tp = 64 Hz when out of test mode
|
||||
- test mode is mostly untested (is used by MS-DOS 6.2x in PC-98xx, and neogeo)
|
||||
- test mode is mostly untested
|
||||
- how does timer-interval differ from timer-pulse?
|
||||
|
||||
*/
|
||||
|
||||
@ -53,9 +52,6 @@ upd1990a_device::upd1990a_device(const machine_config &mconfig, device_type type
|
||||
device_rtc_interface(mconfig, *this),
|
||||
m_write_data(*this),
|
||||
m_write_tp(*this),
|
||||
m_data_out(0),
|
||||
m_c(0),
|
||||
m_clk(0),
|
||||
m_variant(variant)
|
||||
{
|
||||
}
|
||||
@ -65,9 +61,6 @@ upd1990a_device::upd1990a_device(const machine_config &mconfig, const char *tag,
|
||||
device_rtc_interface(mconfig, *this),
|
||||
m_write_data(*this),
|
||||
m_write_tp(*this),
|
||||
m_data_out(0),
|
||||
m_c(0),
|
||||
m_clk(0),
|
||||
m_variant(TYPE_1990A)
|
||||
{
|
||||
}
|
||||
@ -76,6 +69,12 @@ upd4990a_device::upd4990a_device(const machine_config &mconfig, const char *tag,
|
||||
: upd1990a_device(mconfig, UPD4990A, "uPD4990A", tag, owner, clock, TYPE_4990A, "upd4990a", __FILE__) { }
|
||||
|
||||
|
||||
bool upd1990a_device::is_serial_mode()
|
||||
{
|
||||
// uPD4990A is in serial mode if c0/1/2 = high/VDD
|
||||
return (m_variant == TYPE_4990A && m_c_unlatched == 7);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
@ -87,9 +86,26 @@ void upd1990a_device::device_start()
|
||||
m_write_data.resolve_safe();
|
||||
m_write_tp.resolve_safe();
|
||||
|
||||
// initialize
|
||||
set_current_time(machine());
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
m_shift_reg[i] = 0;
|
||||
|
||||
m_oe = 0;
|
||||
m_cs = 0;
|
||||
m_stb = 0;
|
||||
m_data_in = 0;
|
||||
m_data_out = 0;
|
||||
m_c = 0;
|
||||
m_clk = 0;
|
||||
m_tp = 0;
|
||||
m_c_unlatched = 0;
|
||||
m_testmode = false;
|
||||
|
||||
// allocate timers
|
||||
m_timer_clock = timer_alloc(TIMER_CLOCK);
|
||||
m_timer_clock->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
|
||||
m_timer_clock->adjust(attotime::from_hz(clock() / 32768.0), 0, attotime::from_hz(clock() / 32768.0)); // 1 second on XTAL_32_768kHz
|
||||
m_timer_tp = timer_alloc(TIMER_TP);
|
||||
m_timer_data_out = timer_alloc(TIMER_DATA_OUT);
|
||||
m_timer_test_mode = timer_alloc(TIMER_TEST_MODE);
|
||||
@ -106,18 +122,22 @@ void upd1990a_device::device_start()
|
||||
save_item(NAME(m_clk));
|
||||
save_item(NAME(m_tp));
|
||||
save_item(NAME(m_c_unlatched));
|
||||
save_item(NAME(m_testmode));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
// rtc_clock_updated -
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd1990a_device::device_reset()
|
||||
void upd1990a_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
m_tp = 0;
|
||||
m_c_unlatched = 0;
|
||||
set_current_time(machine());
|
||||
m_time_counter[0] = convert_to_bcd(second);
|
||||
m_time_counter[1] = convert_to_bcd(minute);
|
||||
m_time_counter[2] = convert_to_bcd(hour);
|
||||
m_time_counter[3] = convert_to_bcd(day);
|
||||
m_time_counter[4] = (month << 4) | (day_of_week - 1);
|
||||
m_time_counter[5] = convert_to_bcd(year);
|
||||
}
|
||||
|
||||
|
||||
@ -135,50 +155,42 @@ void upd1990a_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
||||
|
||||
case TIMER_TP:
|
||||
m_tp = !m_tp;
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' TP %u\n", tag(), m_tp);
|
||||
|
||||
m_write_tp(m_tp);
|
||||
break;
|
||||
|
||||
case TIMER_DATA_OUT:
|
||||
m_data_out = !m_data_out;
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' DATA OUT TICK %u\n", tag(), m_data_out);
|
||||
|
||||
m_write_data(m_data_out);
|
||||
m_write_data(get_data_out());
|
||||
break;
|
||||
|
||||
case TIMER_TEST_MODE:
|
||||
if (m_oe)
|
||||
{
|
||||
/* TODO: completely untested */
|
||||
/* time counter is advanced at 1024 Hz from "Second" counter input */
|
||||
int i;
|
||||
|
||||
m_data_out = (m_time_counter[4] == 0);
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
/* time counter is advanced from "Second" counter input */
|
||||
int max_shift = is_serial_mode() ? 6 : 5;
|
||||
m_data_out = (m_time_counter[max_shift - 1] == 0);
|
||||
m_write_data(get_data_out());
|
||||
|
||||
for (int i = 0; i < max_shift; i++)
|
||||
{
|
||||
m_time_counter[i]++;
|
||||
if(m_time_counter[i] != 0)
|
||||
if (m_time_counter[i] != 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // parallel
|
||||
else
|
||||
{
|
||||
int i;
|
||||
/* each counter is advanced at 1024 Hz in parallel, overflow carry does not affect next counter */
|
||||
m_time_counter[0]++;
|
||||
m_time_counter[1]++;
|
||||
m_time_counter[2]++;
|
||||
m_time_counter[3]++;
|
||||
m_time_counter[4]++;
|
||||
|
||||
/* each counter is advanced in parallel, overflow carry does not affect next counter */
|
||||
m_data_out = 0;
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
int max_shift = is_serial_mode() ? 6 : 5;
|
||||
for (int i = 0; i < max_shift; i++)
|
||||
{
|
||||
m_time_counter[i]++;
|
||||
m_data_out |= (m_time_counter[i] == 0);
|
||||
}
|
||||
m_write_data(get_data_out());
|
||||
}
|
||||
|
||||
break;
|
||||
@ -186,189 +198,189 @@ void upd1990a_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc_clock_updated -
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd1990a_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
m_time_counter[0] = convert_to_bcd(second);
|
||||
m_time_counter[1] = convert_to_bcd(minute);
|
||||
m_time_counter[2] = convert_to_bcd(hour);
|
||||
m_time_counter[3] = convert_to_bcd(day);
|
||||
m_time_counter[4] = (month << 4) | day_of_week;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// oe_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::oe_w )
|
||||
{
|
||||
if (LOG) logerror("uPD1990A '%s' OE %u\n", tag(), state);
|
||||
|
||||
m_oe = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// cs_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::cs_w )
|
||||
{
|
||||
if (LOG) logerror("uPD1990A '%s' CS %u\n", tag(), state);
|
||||
|
||||
m_cs = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// stb_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::stb_w )
|
||||
{
|
||||
if (!m_cs)
|
||||
return;
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' STB %u\n", tag(), state);
|
||||
|
||||
m_stb = state;
|
||||
|
||||
if (m_cs && m_stb && !m_clk)
|
||||
// rising edge
|
||||
if (!m_stb && state)
|
||||
{
|
||||
m_c = m_c_unlatched; // if STB = 1, latch in the command bits
|
||||
// read command
|
||||
if (is_serial_mode())
|
||||
m_c = m_shift_reg[6];
|
||||
else
|
||||
{
|
||||
m_c = m_c_unlatched;
|
||||
if (m_c == 7)
|
||||
m_c = MODE_TEST;
|
||||
}
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' Command %x\n", tag(), m_c);
|
||||
|
||||
// common functions
|
||||
if (m_c == MODE_REGISTER_HOLD || (m_c >= MODE_TP_64HZ && m_c < MODE_TEST))
|
||||
{
|
||||
// enable time counter
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
// disable testmode
|
||||
m_testmode = false;
|
||||
m_timer_test_mode->enable(0);
|
||||
}
|
||||
|
||||
switch (m_c)
|
||||
{
|
||||
case MODE_REGISTER_HOLD:
|
||||
if (LOG) logerror("uPD1990A '%s' Register Hold Mode\n", tag());
|
||||
// 1Hz data out pulse
|
||||
m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz((clock() / 32768.0) * 2.0));
|
||||
|
||||
/* enable time counter */
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* 1 Hz data out pulse */
|
||||
m_data_out = 1;
|
||||
m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz(1*2));
|
||||
|
||||
/* 64 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(64*2));
|
||||
// 64Hz time pulse
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz((clock() / 512.0) * 2.0));
|
||||
break;
|
||||
|
||||
case MODE_SHIFT:
|
||||
if (LOG) logerror("uPD1990A '%s' Shift Mode\n", tag());
|
||||
// enable time counter
|
||||
if (!m_testmode)
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
/* enable time counter */
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
/* disable data out pulse */
|
||||
// data out LSB of shift register
|
||||
m_timer_data_out->enable(0);
|
||||
m_data_out = m_shift_reg[0] & 1;
|
||||
m_write_data(get_data_out());
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
// 32Hz time pulse in testmode
|
||||
if (m_testmode)
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz((clock() / 1024.0) * 2.0));
|
||||
|
||||
/* output LSB of shift register */
|
||||
m_data_out = BIT(m_shift_reg[0], 0);
|
||||
m_write_data(m_data_out);
|
||||
|
||||
/* 32 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
|
||||
break;
|
||||
|
||||
case MODE_TIME_SET:
|
||||
if (LOG) logerror("uPD1990A '%s' Time Set Mode\n", tag());
|
||||
if (LOG) logerror("uPD1990A '%s' Shift Register %02x%02x%02x%02x%02x\n", tag(), m_shift_reg[4], m_shift_reg[3], m_shift_reg[2], m_shift_reg[1], m_shift_reg[0]);
|
||||
|
||||
/* disable time counter */
|
||||
{
|
||||
// disable time counter
|
||||
m_timer_clock->enable(0);
|
||||
|
||||
/* disable data out pulse */
|
||||
// data out LSB of shift register
|
||||
m_timer_data_out->enable(0);
|
||||
m_data_out = m_shift_reg[0] & 1;
|
||||
m_write_data(get_data_out());
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* output LSB of shift register */
|
||||
m_data_out = BIT(m_shift_reg[0], 0);
|
||||
m_write_data(m_data_out);
|
||||
|
||||
/* load shift register data into time counter */
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
// load shift register data into time counter
|
||||
int max_shift = is_serial_mode() ? 6 : 5;
|
||||
for (int i = 0; i < max_shift; i++)
|
||||
m_time_counter[i] = m_shift_reg[i];
|
||||
|
||||
set_time(false, 0, m_time_counter[4] >> 4, m_time_counter[4] & 0x0f, m_time_counter[3], m_time_counter[2], m_time_counter[1], m_time_counter[0]);
|
||||
set_time(false,
|
||||
bcd_to_integer(m_time_counter[5]),
|
||||
m_time_counter[4] >> 4,
|
||||
bcd_to_integer(m_time_counter[3]),
|
||||
(m_time_counter[4] & 0xf) + 1,
|
||||
bcd_to_integer(m_time_counter[2]),
|
||||
bcd_to_integer(m_time_counter[1]),
|
||||
bcd_to_integer(m_time_counter[0])
|
||||
);
|
||||
|
||||
// reset stage 10-15 of clock divider
|
||||
m_timer_clock->adjust(attotime::from_ticks(m_timer_clock->remaining().as_ticks(clock()) % (clock() / 512), clock()), 0, attotime::from_hz(clock() / 32768.0));
|
||||
|
||||
// disable(low) time pulse in testmode
|
||||
if (m_testmode)
|
||||
{
|
||||
m_timer_tp->enable(0);
|
||||
m_tp = 0;
|
||||
m_write_tp(m_tp);
|
||||
}
|
||||
|
||||
/* 32 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_TIME_READ:
|
||||
if (LOG) logerror("uPD1990A '%s' Time Read Mode\n", tag());
|
||||
{
|
||||
// enable time counter
|
||||
if (!m_testmode)
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
/* enable time counter */
|
||||
m_timer_clock->enable(1);
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* load time counter data into shift register */
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
// load time counter data into shift register
|
||||
int max_shift = is_serial_mode() ? 6 : 5;
|
||||
for (int i = 0; i < max_shift; i++)
|
||||
m_shift_reg[i] = m_time_counter[i];
|
||||
}
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' Shift Register %02x%02x%02x%02x%02x\n", tag(), m_shift_reg[4], m_shift_reg[3], m_shift_reg[2], m_shift_reg[1], m_shift_reg[0]);
|
||||
// data out pulse: uPD4990A: 1Hz, uPD1990A: 512Hz in testmode, 0.5Hz in normal mode
|
||||
float div;
|
||||
if (m_variant == TYPE_4990A)
|
||||
div = 32768.0;
|
||||
else if (m_testmode)
|
||||
div = 64.0;
|
||||
else div = 65536.0;
|
||||
|
||||
/* 512 Hz data out pulse */
|
||||
m_data_out = 1;
|
||||
m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz(512*2));
|
||||
m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz((clock() / div) * 2.0));
|
||||
|
||||
// 32Hz time pulse in testmode
|
||||
if (m_testmode)
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz((clock() / 1024.0) * 2.0));
|
||||
|
||||
/* 32 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_TP_64HZ_SET:
|
||||
if (LOG) logerror("uPD1990A '%s' TP = 64 Hz Set Mode\n", tag());
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* 64 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(64*2));
|
||||
case MODE_TP_64HZ:
|
||||
case MODE_TP_256HZ:
|
||||
case MODE_TP_2048HZ:
|
||||
case MODE_TP_4096HZ:
|
||||
{
|
||||
// set timer pulse
|
||||
const float div[4] = { 512.0, 128.0, 16.0, 8.0 };
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz((clock() / div[m_c - MODE_TP_64HZ]) * 2.0));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_TP_256HZ_SET:
|
||||
if (LOG) logerror("uPD1990A '%s' TP = 256 Hz Set Mode\n", tag());
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* 256 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(256*2));
|
||||
case MODE_TP_1S_INT:
|
||||
case MODE_TP_10S_INT:
|
||||
case MODE_TP_30S_INT:
|
||||
case MODE_TP_60S_INT:
|
||||
{
|
||||
// set timer pulse
|
||||
attotime one_second = attotime::from_hz(clock() / 32768.0);
|
||||
const float mul[4] = { 1.0, 10.0, 30.0, 60.0 };
|
||||
m_timer_tp->adjust(attotime::zero, 0, one_second * mul[m_c - MODE_TP_1S_INT] / 2.0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_TP_2048HZ_SET:
|
||||
if (LOG) logerror("uPD1990A '%s' TP = 2048 Hz Set Mode\n", tag());
|
||||
|
||||
m_timer_test_mode->enable(0);
|
||||
|
||||
/* 2048 Hz time pulse */
|
||||
m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(2048*2));
|
||||
case MODE_INT_RESET_OUTPUT:
|
||||
case MODE_INT_RUN_CLOCK:
|
||||
case MODE_INT_STOP_CLOCK:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case MODE_TEST:
|
||||
if (LOG) logerror("uPD1990A '%s' Test Mode\n", tag());
|
||||
|
||||
/* disable time counter */
|
||||
{
|
||||
// disable time counter
|
||||
m_timer_clock->enable(0);
|
||||
|
||||
/* disable data out pulse */
|
||||
// disable data out pulse
|
||||
m_timer_data_out->enable(0);
|
||||
|
||||
// enable testmode
|
||||
m_testmode = true;
|
||||
m_timer_test_mode->enable(1);
|
||||
|
||||
m_timer_test_mode->adjust(attotime::zero, 0, attotime::from_hz(1024));
|
||||
const float div = (m_variant == TYPE_4990A) ? 4.0 : 32.0; // uPD4990A: 8192Hz, uPD1990A: 1024Hz
|
||||
m_timer_test_mode->adjust(attotime::zero, 0, attotime::from_hz(clock() / div));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_stb = state;
|
||||
}
|
||||
|
||||
|
||||
@ -378,35 +390,40 @@ WRITE_LINE_MEMBER( upd1990a_device::stb_w )
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::clk_w )
|
||||
{
|
||||
if (!m_cs)
|
||||
return;
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' CLK %u\n", tag(), state);
|
||||
|
||||
if (!m_clk && state) // rising edge
|
||||
// rising edge
|
||||
if (!m_clk && state)
|
||||
{
|
||||
int in = m_data_in;
|
||||
|
||||
if (is_serial_mode())
|
||||
{
|
||||
// always clock serial command register
|
||||
in = m_shift_reg[6] & 1;
|
||||
m_shift_reg[6] >>= 1;
|
||||
m_shift_reg[6] |= (m_data_in << 3);
|
||||
}
|
||||
|
||||
if (m_c == MODE_SHIFT)
|
||||
{
|
||||
m_shift_reg[0] >>= 1;
|
||||
m_shift_reg[0] |= (BIT(m_shift_reg[1], 0) << 7);
|
||||
|
||||
m_shift_reg[1] >>= 1;
|
||||
m_shift_reg[1] |= (BIT(m_shift_reg[2], 0) << 7);
|
||||
|
||||
m_shift_reg[2] >>= 1;
|
||||
m_shift_reg[2] |= (BIT(m_shift_reg[3], 0) << 7);
|
||||
|
||||
m_shift_reg[3] >>= 1;
|
||||
m_shift_reg[3] |= (BIT(m_shift_reg[4], 0) << 7);
|
||||
|
||||
m_shift_reg[4] >>= 1;
|
||||
m_shift_reg[4] |= (m_data_in << 7);
|
||||
|
||||
if (m_oe)
|
||||
// clock shift register
|
||||
int max_shift = is_serial_mode() ? 6 : 5;
|
||||
for (int i = 0; i < max_shift; i++)
|
||||
{
|
||||
m_data_out = BIT(m_shift_reg[0], 0);
|
||||
|
||||
if (LOG) logerror("uPD1990A '%s' DATA OUT %u\n", tag(), m_data_out);
|
||||
|
||||
m_write_data(m_data_out);
|
||||
m_shift_reg[i] >>= 1;
|
||||
if (i == (max_shift - 1))
|
||||
m_shift_reg[i] |= (in << 7); // shift in new bit
|
||||
else
|
||||
m_shift_reg[i] |= (m_shift_reg[i + 1] << 7 & 0x80);
|
||||
}
|
||||
|
||||
// data out LSB of shift register
|
||||
m_data_out = m_shift_reg[0] & 1;
|
||||
m_write_data(get_data_out());
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,66 +432,69 @@ WRITE_LINE_MEMBER( upd1990a_device::clk_w )
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// c0_w -
|
||||
// misc input pins
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::cs_w )
|
||||
{
|
||||
// chip select
|
||||
if (LOG) logerror("uPD1990A '%s' CS %u\n", tag(), state);
|
||||
m_cs = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::oe_w )
|
||||
{
|
||||
// output enable
|
||||
if (LOG) logerror("uPD1990A '%s' OE %u\n", tag(), state);
|
||||
|
||||
int prev_oe = m_oe;
|
||||
m_oe = state;
|
||||
|
||||
if (m_oe != prev_oe && m_c != MODE_TEST)
|
||||
m_write_data(get_data_out());
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::c0_w )
|
||||
{
|
||||
if (LOG) logerror("uPD1990A '%s' C0 %u\n", tag(), state);
|
||||
|
||||
m_c_unlatched = (m_c_unlatched & 0x06) | state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// c1_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::c1_w )
|
||||
{
|
||||
if (LOG) logerror("uPD1990A '%s' C1 %u\n", tag(), state);
|
||||
|
||||
m_c_unlatched = (m_c_unlatched & 0x05) | (state << 1);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// c2_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::c2_w )
|
||||
{
|
||||
if (LOG) logerror("uPD1990A '%s' C2 %u\n", tag(), state);
|
||||
|
||||
m_c_unlatched = (m_c_unlatched & 0x03) | (state << 2);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// data_in_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( upd1990a_device::data_in_w )
|
||||
{
|
||||
// data input
|
||||
if (LOG) logerror("uPD1990A '%s' DATA IN %u\n", tag(), state);
|
||||
|
||||
m_data_in = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// data_out_r -
|
||||
// output pins
|
||||
//-------------------------------------------------
|
||||
|
||||
READ_LINE_MEMBER( upd1990a_device::data_out_r )
|
||||
int upd1990a_device::get_data_out()
|
||||
{
|
||||
return m_data_out;
|
||||
// except when in testmode, data_out is high impedance when OE is low
|
||||
return (m_oe || m_testmode) ? m_data_out : 1;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// tp_r -
|
||||
//-------------------------------------------------
|
||||
READ_LINE_MEMBER( upd1990a_device::data_out_r )
|
||||
{
|
||||
return get_data_out();
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER( upd1990a_device::tp_r )
|
||||
{
|
||||
|
@ -75,7 +75,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
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
|
||||
@ -102,35 +101,48 @@ private:
|
||||
MODE_SHIFT,
|
||||
MODE_TIME_SET,
|
||||
MODE_TIME_READ,
|
||||
MODE_TP_64HZ_SET,
|
||||
MODE_TP_256HZ_SET,
|
||||
MODE_TP_2048HZ_SET,
|
||||
MODE_TP_64HZ,
|
||||
MODE_TP_256HZ,
|
||||
MODE_TP_2048HZ,
|
||||
MODE_TP_4096HZ,
|
||||
MODE_TP_1S_INT,
|
||||
MODE_TP_10S_INT,
|
||||
MODE_TP_30S_INT,
|
||||
MODE_TP_60S_INT,
|
||||
MODE_INT_RESET_OUTPUT,
|
||||
MODE_INT_RUN_CLOCK,
|
||||
MODE_INT_STOP_CLOCK,
|
||||
MODE_TEST
|
||||
};
|
||||
|
||||
devcb2_write_line m_write_data;
|
||||
devcb2_write_line m_write_tp;
|
||||
devcb2_write_line m_write_data;
|
||||
devcb2_write_line m_write_tp;
|
||||
|
||||
UINT8 m_time_counter[5]; // time counter
|
||||
UINT8 m_shift_reg[5]; // shift register
|
||||
UINT8 m_time_counter[6]; // time counter
|
||||
UINT8 m_shift_reg[7]; // shift register (40 bits, or 48 bits + serial command register)
|
||||
|
||||
int m_oe; // output enable
|
||||
int m_cs; // chip select
|
||||
int m_stb; // strobe
|
||||
int m_data_in; // data in
|
||||
int m_data_out; // data out
|
||||
int m_c; // command
|
||||
int m_c; // latched command
|
||||
int m_clk; // shift clock
|
||||
int m_tp; // time pulse
|
||||
int m_c_unlatched; // command waiting for STB
|
||||
|
||||
int m_variant;
|
||||
bool m_testmode; // testmode active
|
||||
|
||||
int m_variant;
|
||||
|
||||
// timers
|
||||
emu_timer *m_timer_clock;
|
||||
emu_timer *m_timer_tp;
|
||||
emu_timer *m_timer_data_out;
|
||||
emu_timer *m_timer_test_mode;
|
||||
|
||||
bool is_serial_mode();
|
||||
int get_data_out();
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user