6522via.cpp: Count negative PB6 pulses in T2 counter mode

(nw) VIA interrupt remains disconnected in tv950 due to CRTC-related problems. This is fairly likely to cause regressions in other drivers which may need explicit writes to PB6.
This commit is contained in:
AJR 2018-12-27 15:48:33 -05:00
parent bbc1fcfed3
commit 6aa1dbe27d
3 changed files with 103 additions and 54 deletions

View File

@ -7,8 +7,6 @@
This is based on the M6821 emulation in MAME. This is based on the M6821 emulation in MAME.
To do: To do:
T2 pulse counting mode
Pulse mode handshake output Pulse mode handshake output
**********************************************************************/ **********************************************************************/
@ -139,6 +137,29 @@ uint16_t via6522_device::get_counter1_value()
return val; return val;
} }
void via6522_device::counter2_decrement()
{
if (!T2_COUNT_PB6(m_acr))
return;
// count down on T2CL
if (m_t2cl-- != 0)
return;
// borrow from T2CH
if (m_t2ch-- != 0)
return;
// underflow causes only one interrupt between T2CH writes
if (m_t2_active)
{
m_t2_active = 0;
LOGINT("T2 INT request ");
set_int(INT_T2);
}
}
//************************************************************************** //**************************************************************************
// LIVE DEVICE // LIVE DEVICE
@ -170,7 +191,7 @@ via6522_device::via6522_device(const machine_config &mconfig, const char *tag, d
m_in_ca1(0), m_in_ca1(0),
m_in_ca2(0), m_in_ca2(0),
m_out_ca2(0), m_out_ca2(0),
m_in_b(0), m_in_b(0xff),
m_in_cb1(0), m_in_cb1(0),
m_in_cb2(0), m_in_cb2(0),
m_pcr(0), m_pcr(0),
@ -283,6 +304,12 @@ void via6522_device::device_reset()
m_ca2_handler(m_out_ca2); m_ca2_handler(m_out_ca2);
m_cb1_handler(m_out_cb1); m_cb1_handler(m_out_cb1);
m_cb2_handler(m_out_cb2); m_cb2_handler(m_out_cb2);
m_t1->adjust(attotime::never);
m_t2->adjust(attotime::never);
m_ca2_timer->adjust(attotime::never);
m_shift_timer->adjust(attotime::never);
m_shift_irq_timer->adjust(attotime::never);
} }
@ -487,16 +514,15 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
uint8_t via6522_device::input_pa() uint8_t via6522_device::input_pa()
{ {
uint8_t pa = m_in_a & ~m_ddr_a;
/// TODO: REMOVE THIS /// TODO: REMOVE THIS
if (!m_in_a_handler.isnull()) if (m_ddr_a != 0xff && !m_in_a_handler.isnull())
{ pa &= m_in_a_handler();
if (m_ddr_a != 0xff)
m_in_a = m_in_a_handler(0);
return (m_out_a & m_ddr_a) + (m_in_a & ~m_ddr_a); pa |= m_out_a & m_ddr_a;
}
return m_in_a & (m_out_a | ~m_ddr_a); return pa;
} }
void via6522_device::output_pa() void via6522_device::output_pa()
@ -507,13 +533,15 @@ void via6522_device::output_pa()
uint8_t via6522_device::input_pb() uint8_t via6522_device::input_pb()
{ {
uint8_t pb = m_in_b & ~m_ddr_b;
/// TODO: REMOVE THIS /// TODO: REMOVE THIS
if (m_ddr_b != 0xff && !m_in_b_handler.isnull()) if (m_ddr_b != 0xff && !m_in_b_handler.isnull())
{ {
m_in_b = m_in_b_handler(0); pb &= m_in_b_handler();
} }
uint8_t pb = (m_out_b & m_ddr_b) + (m_in_b & ~m_ddr_b); pb |= m_out_b & m_ddr_b;
if (T1_SET_PB7(m_acr)) if (T1_SET_PB7(m_acr))
pb = (pb & 0x7f) | (m_t1_pb7 << 7); pb = (pb & 0x7f) | (m_t1_pb7 << 7);
@ -538,9 +566,6 @@ void via6522_device::output_pb()
u8 via6522_device::read(offs_t offset) u8 via6522_device::read(offs_t offset)
{ {
int val = 0; int val = 0;
if (machine().side_effects_disabled())
return 0;
offset &= 0xf; offset &= 0xf;
switch (offset) switch (offset)
@ -556,8 +581,11 @@ u8 via6522_device::read(offs_t offset)
val = m_latch_b; val = m_latch_b;
} }
if (!machine().side_effects_disabled())
{
LOGINT("PB INT "); LOGINT("PB INT ");
CLR_PB_INT(); CLR_PB_INT();
}
break; break;
case VIA_PA: case VIA_PA:
@ -571,6 +599,8 @@ u8 via6522_device::read(offs_t offset)
val = m_latch_a; val = m_latch_a;
} }
if (!machine().side_effects_disabled())
{
LOGINT("PA INT "); LOGINT("PA INT ");
CLR_PA_INT(); CLR_PA_INT();
@ -582,6 +612,7 @@ u8 via6522_device::read(offs_t offset)
if (CA2_PULSE_OUTPUT(m_pcr)) if (CA2_PULSE_OUTPUT(m_pcr))
m_ca2_timer->adjust(clocks_to_attotime(1)); m_ca2_timer->adjust(clocks_to_attotime(1));
}
break; break;
@ -606,8 +637,11 @@ u8 via6522_device::read(offs_t offset)
break; break;
case VIA_T1CL: case VIA_T1CL:
if (!machine().side_effects_disabled())
{
LOGINT("T1CL INT "); LOGINT("T1CL INT ");
clear_int(INT_T1); clear_int(INT_T1);
}
val = get_counter1_value() & 0xFF; val = get_counter1_value() & 0xFF;
break; break;
@ -624,9 +658,12 @@ u8 via6522_device::read(offs_t offset)
break; break;
case VIA_T2CL: case VIA_T2CL:
if (!machine().side_effects_disabled())
{
LOGINT("T2CL INT "); LOGINT("T2CL INT ");
clear_int(INT_T2); clear_int(INT_T2);
if (m_t2_active) }
if (m_t2_active && m_t2->enabled())
{ {
val = attotime_to_clocks(m_t2->remaining()) & 0xff; val = attotime_to_clocks(m_t2->remaining()) & 0xff;
} }
@ -644,7 +681,7 @@ u8 via6522_device::read(offs_t offset)
break; break;
case VIA_T2CH: case VIA_T2CH:
if (m_t2_active) if (m_t2_active && m_t2->enabled())
{ {
val = attotime_to_clocks(m_t2->remaining()) >> 8; val = attotime_to_clocks(m_t2->remaining()) >> 8;
} }
@ -664,6 +701,8 @@ u8 via6522_device::read(offs_t offset)
case VIA_SR: case VIA_SR:
LOGSHIFT("Read SR: %02x ", m_sr); LOGSHIFT("Read SR: %02x ", m_sr);
val = m_sr; val = m_sr;
if (!machine().side_effects_disabled())
{
m_out_cb1 = 1; m_out_cb1 = 1;
m_cb1_handler(m_out_cb1); m_cb1_handler(m_out_cb1);
m_shift_counter = 0x0f; m_shift_counter = 0x0f;
@ -686,6 +725,7 @@ u8 via6522_device::read(offs_t offset)
LOGSHIFT("Timer stops"); LOGSHIFT("Timer stops");
} }
LOGSHIFT("\n"); LOGSHIFT("\n");
}
break; break;
case VIA_PCR: case VIA_PCR:
@ -839,7 +879,7 @@ void via6522_device::write(offs_t offset, u8 data)
} }
else else
{ {
m_t2->adjust(clocks_to_attotime(TIMER2_VALUE)); //m_t2->adjust(clocks_to_attotime(TIMER2_VALUE));
m_t2_active = 1; m_t2_active = 1;
m_time2 = machine().time(); m_time2 = machine().time();
} }
@ -1025,11 +1065,19 @@ void via6522_device::set_pb_line(int line, int state)
if (state) if (state)
m_in_b |= (1 << line); m_in_b |= (1 << line);
else else
{
if (line == 6 && BIT(m_in_b, 6))
counter2_decrement();
m_in_b &= ~(1 << line); m_in_b &= ~(1 << line);
} }
}
WRITE8_MEMBER( via6522_device::write_pb ) WRITE8_MEMBER( via6522_device::write_pb )
{ {
if (!BIT(data, 6) && BIT(m_in_b, 6))
counter2_decrement();
m_in_b = data; m_in_b = data;
} }

View File

@ -107,6 +107,7 @@ private:
static constexpr device_timer_id TIMER_SHIFT_IRQ = 4; static constexpr device_timer_id TIMER_SHIFT_IRQ = 4;
uint16_t get_counter1_value(); uint16_t get_counter1_value();
void counter2_decrement();
void set_int(int data); void set_int(int data);
void clear_int(int data); void clear_int(int data);

View File

@ -201,7 +201,7 @@ void esprit_state::esprit3(machine_config &config)
crtc.set_char_width(9); crtc.set_char_width(9);
crtc.set_update_row_callback(FUNC(esprit_state::crtc_update_row), this); crtc.set_update_row_callback(FUNC(esprit_state::crtc_update_row), this);
crtc.set_on_update_addr_change_callback(FUNC(esprit_state::crtc_update_addr), this); crtc.set_on_update_addr_change_callback(FUNC(esprit_state::crtc_update_addr), this);
//crtc.out_hsync_callback().set("via", FUNC(via6522_device::write_pb6)).invert(); crtc.out_hsync_callback().set("via", FUNC(via6522_device::write_pb6)).invert();
} }
ROM_START( esprit ) ROM_START( esprit )