summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/6522via.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/6522via.cpp')
-rw-r--r--src/devices/machine/6522via.cpp154
1 files changed, 101 insertions, 53 deletions
diff --git a/src/devices/machine/6522via.cpp b/src/devices/machine/6522via.cpp
index eae073196b0..f9b61761a6c 100644
--- a/src/devices/machine/6522via.cpp
+++ b/src/devices/machine/6522via.cpp
@@ -7,8 +7,6 @@
This is based on the M6821 emulation in MAME.
To do:
-
- T2 pulse counting mode
Pulse mode handshake output
**********************************************************************/
@@ -139,6 +137,29 @@ uint16_t via6522_device::get_counter1_value()
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
@@ -170,7 +191,7 @@ via6522_device::via6522_device(const machine_config &mconfig, const char *tag, d
m_in_ca1(0),
m_in_ca2(0),
m_out_ca2(0),
- m_in_b(0),
+ m_in_b(0xff),
m_in_cb1(0),
m_in_cb2(0),
m_pcr(0),
@@ -283,6 +304,12 @@ void via6522_device::device_reset()
m_ca2_handler(m_out_ca2);
m_cb1_handler(m_out_cb1);
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 pa = m_in_a & ~m_ddr_a;
+
/// TODO: REMOVE THIS
- if (!m_in_a_handler.isnull())
- {
- if (m_ddr_a != 0xff)
- m_in_a = m_in_a_handler(0);
+ if (m_ddr_a != 0xff && !m_in_a_handler.isnull())
+ pa &= m_in_a_handler();
- 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()
@@ -507,13 +533,15 @@ void via6522_device::output_pa()
uint8_t via6522_device::input_pb()
{
+ uint8_t pb = m_in_b & ~m_ddr_b;
+
/// TODO: REMOVE THIS
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))
pb = (pb & 0x7f) | (m_t1_pb7 << 7);
@@ -538,9 +566,6 @@ void via6522_device::output_pb()
u8 via6522_device::read(offs_t offset)
{
int val = 0;
- if (machine().side_effects_disabled())
- return 0;
-
offset &= 0xf;
switch (offset)
@@ -556,8 +581,11 @@ u8 via6522_device::read(offs_t offset)
val = m_latch_b;
}
- LOGINT("PB INT ");
- CLR_PB_INT();
+ if (!machine().side_effects_disabled())
+ {
+ LOGINT("PB INT ");
+ CLR_PB_INT();
+ }
break;
case VIA_PA:
@@ -571,17 +599,20 @@ u8 via6522_device::read(offs_t offset)
val = m_latch_a;
}
- LOGINT("PA INT ");
- CLR_PA_INT();
-
- if (m_out_ca2 && (CA2_PULSE_OUTPUT(m_pcr) || CA2_AUTO_HS(m_pcr)))
+ if (!machine().side_effects_disabled())
{
- m_out_ca2 = 0;
- m_ca2_handler(m_out_ca2);
- }
+ LOGINT("PA INT ");
+ CLR_PA_INT();
- if (CA2_PULSE_OUTPUT(m_pcr))
- m_ca2_timer->adjust(clocks_to_attotime(1));
+ if (m_out_ca2 && (CA2_PULSE_OUTPUT(m_pcr) || CA2_AUTO_HS(m_pcr)))
+ {
+ m_out_ca2 = 0;
+ m_ca2_handler(m_out_ca2);
+ }
+
+ if (CA2_PULSE_OUTPUT(m_pcr))
+ m_ca2_timer->adjust(clocks_to_attotime(1));
+ }
break;
@@ -606,8 +637,11 @@ u8 via6522_device::read(offs_t offset)
break;
case VIA_T1CL:
- LOGINT("T1CL INT ");
- clear_int(INT_T1);
+ if (!machine().side_effects_disabled())
+ {
+ LOGINT("T1CL INT ");
+ clear_int(INT_T1);
+ }
val = get_counter1_value() & 0xFF;
break;
@@ -624,9 +658,12 @@ u8 via6522_device::read(offs_t offset)
break;
case VIA_T2CL:
- LOGINT("T2CL INT ");
- clear_int(INT_T2);
- if (m_t2_active)
+ if (!machine().side_effects_disabled())
+ {
+ LOGINT("T2CL INT ");
+ clear_int(INT_T2);
+ }
+ if (m_t2_active && m_t2->enabled())
{
val = attotime_to_clocks(m_t2->remaining()) & 0xff;
}
@@ -644,7 +681,7 @@ u8 via6522_device::read(offs_t offset)
break;
case VIA_T2CH:
- if (m_t2_active)
+ if (m_t2_active && m_t2->enabled())
{
val = attotime_to_clocks(m_t2->remaining()) >> 8;
}
@@ -664,28 +701,31 @@ u8 via6522_device::read(offs_t offset)
case VIA_SR:
LOGSHIFT("Read SR: %02x ", m_sr);
val = m_sr;
- m_out_cb1 = 1;
- m_cb1_handler(m_out_cb1);
- m_shift_counter = 0x0f;
- LOGINT("SR INT ");
- clear_int(INT_SR);
- LOGSHIFT(" - ACR: %02x ", m_acr);
- if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
- {
- m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 flanks to start shifter from a read
- LOGSHIFT(" - read SR starts O2 timer ");
- }
- else if (SI_T2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr))
- {
- m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2) / 2);
- LOGSHIFT(" - read SR starts T2 timer ");
- }
- else if (! SO_T2_RATE(m_acr))
+ if (!machine().side_effects_disabled())
{
- m_shift_timer->adjust(attotime::never);
- LOGSHIFT("Timer stops");
+ m_out_cb1 = 1;
+ m_cb1_handler(m_out_cb1);
+ m_shift_counter = 0x0f;
+ LOGINT("SR INT ");
+ clear_int(INT_SR);
+ LOGSHIFT(" - ACR: %02x ", m_acr);
+ if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 flanks to start shifter from a read
+ LOGSHIFT(" - read SR starts O2 timer ");
+ }
+ else if (SI_T2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2) / 2);
+ LOGSHIFT(" - read SR starts T2 timer ");
+ }
+ else if (!SO_T2_RATE(m_acr))
+ {
+ m_shift_timer->adjust(attotime::never);
+ LOGSHIFT("Timer stops");
+ }
+ LOGSHIFT("\n");
}
- LOGSHIFT("\n");
break;
case VIA_PCR:
@@ -839,7 +879,7 @@ void via6522_device::write(offs_t offset, u8 data)
}
else
{
- m_t2->adjust(clocks_to_attotime(TIMER2_VALUE));
+ //m_t2->adjust(clocks_to_attotime(TIMER2_VALUE));
m_t2_active = 1;
m_time2 = machine().time();
}
@@ -1025,11 +1065,19 @@ void via6522_device::set_pb_line(int line, int state)
if (state)
m_in_b |= (1 << line);
else
+ {
+ if (line == 6 && BIT(m_in_b, 6))
+ counter2_decrement();
+
m_in_b &= ~(1 << line);
+ }
}
WRITE8_MEMBER( via6522_device::write_pb )
{
+ if (!BIT(data, 6) && BIT(m_in_b, 6))
+ counter2_decrement();
+
m_in_b = data;
}