n68681: Implement OP3 toggle on timer expire and input delta interrupts. [R. Belmont]

nw: Yes, we're going to start phasing out the old pull method of reading the input ports in order to facilitate the input delta handling.
This commit is contained in:
R. Belmont 2014-01-20 04:40:53 +00:00
parent c756096a7e
commit c959f1ac0e
2 changed files with 123 additions and 11 deletions

View File

@ -226,7 +226,12 @@ TIMER_CALLBACK_MEMBER( duartn68681_device::duart_timer_callback )
// Timer mode // Timer mode
half_period ^= 1; half_period ^= 1;
// TODO: Set OP3 // timer output to bit 3?
if ((OPCR & 0xc) == 0x4)
{
OPR ^= 0x8;
write_outport(OPR ^ 0xff);
}
if (!half_period) if (!half_period)
{ {
@ -265,11 +270,11 @@ READ8_MEMBER( duartn68681_device::read )
case 0x04: /* IPCR */ case 0x04: /* IPCR */
{ {
UINT8 IP = read_inport(); r = IPCR;
r = (((IP_last_state ^ IP) & 0x0f) << 4) | (IP & 0x0f); // reading this clears all the input change bits
IP_last_state = IP; IPCR &= 0x0f;
ISR &= ~INT_INPUT_PORT_CHANGE; ISR &= ~INT_INPUT_PORT_CHANGE;
update_interrupts(); update_interrupts();
} }
break; break;
@ -293,8 +298,8 @@ READ8_MEMBER( duartn68681_device::read )
break; break;
case 0x0d: /* IP */ case 0x0d: /* IP */
r = read_inport(); r = read_inport(); // TODO: go away
break; break;
case 0x0e: /* Start counter command */ case 0x0e: /* Start counter command */
{ {
@ -302,7 +307,6 @@ READ8_MEMBER( duartn68681_device::read )
{ {
// Reset the timer // Reset the timer
half_period = 0; half_period = 0;
// TODO: Set OP3 to 1
} }
int count = MAX(CTR.w.l, 1); int count = MAX(CTR.w.l, 1);
@ -357,7 +361,6 @@ WRITE8_MEMBER( duartn68681_device::write )
UINT16 count = MAX(CTR.w.l, 1); UINT16 count = MAX(CTR.w.l, 1);
half_period = 0; half_period = 0;
// TODO: Set OP3
duart68681_start_ct(count); duart68681_start_ct(count);
} }
else else
@ -367,9 +370,15 @@ WRITE8_MEMBER( duartn68681_device::write )
} }
} }
// check for pending input port delta interrupts
if ((((IPCR>>4) & data) & 0x0f) != 0)
{
ISR |= INT_INPUT_PORT_CHANGE;
}
m_chanA->ACR_updated(); m_chanA->ACR_updated();
m_chanB->ACR_updated(); m_chanB->ACR_updated();
m_chanA->update_interrupts(); // need to add ACR checking for IP delta ints m_chanA->update_interrupts();
m_chanB->update_interrupts(); m_chanB->update_interrupts();
update_interrupts(); update_interrupts();
break; break;
@ -399,7 +408,7 @@ WRITE8_MEMBER( duartn68681_device::write )
break; break;
case 0x0d: /* OPCR */ case 0x0d: /* OPCR */
if (data != 0x00) if ((data != 0x00) && ((data & 0xc) != 0x4))
logerror( "68681 (%s): Unhandled OPCR value: %02x\n", tag(), data); logerror( "68681 (%s): Unhandled OPCR value: %02x\n", tag(), data);
OPCR = data; OPCR = data;
break; break;
@ -416,6 +425,100 @@ WRITE8_MEMBER( duartn68681_device::write )
} }
} }
WRITE_LINE_MEMBER( duartn68681_device::ip0_w )
{
UINT8 newIP = (IP_last_state & ~0x01) | (state == ASSERT_LINE) ? 1 : 0;
if (newIP != IP_last_state)
{
IPCR &= ~0x0f;
IPCR |= (newIP & 0x0f);
IPCR |= 0x10;
if (ACR & 1)
{
ISR |= INT_INPUT_PORT_CHANGE;
update_interrupts();
}
}
IP_last_state = newIP;
}
WRITE_LINE_MEMBER( duartn68681_device::ip1_w )
{
UINT8 newIP = (IP_last_state & ~0x02) | (state == ASSERT_LINE) ? 2 : 0;
if (newIP != IP_last_state)
{
IPCR &= ~0x0f;
IPCR |= (newIP & 0x0f);
IPCR |= 0x20;
if (ACR & 2)
{
ISR |= INT_INPUT_PORT_CHANGE;
update_interrupts();
}
}
IP_last_state = newIP;
}
WRITE_LINE_MEMBER( duartn68681_device::ip2_w )
{
UINT8 newIP = (IP_last_state & ~0x04) | (state == ASSERT_LINE) ? 4 : 0;
if (newIP != IP_last_state)
{
IPCR &= ~0x0f;
IPCR |= (newIP & 0x0f);
IPCR |= 0x40;
if (ACR & 4)
{
ISR |= INT_INPUT_PORT_CHANGE;
update_interrupts();
}
}
IP_last_state = newIP;
}
WRITE_LINE_MEMBER( duartn68681_device::ip3_w )
{
UINT8 newIP = (IP_last_state & ~0x08) | (state == ASSERT_LINE) ? 8 : 0;
if (newIP != IP_last_state)
{
IPCR &= ~0x0f;
IPCR |= (newIP & 0x0f);
IPCR |= 0x80;
if (ACR & 8)
{
ISR |= INT_INPUT_PORT_CHANGE;
update_interrupts();
}
}
IP_last_state = newIP;
}
WRITE_LINE_MEMBER( duartn68681_device::ip4_w )
{
UINT8 newIP = (IP_last_state & ~0x10) | (state == ASSERT_LINE) ? 0x10 : 0;
// TODO: special mode for ip4
IP_last_state = newIP;
}
WRITE_LINE_MEMBER( duartn68681_device::ip5_w )
{
UINT8 newIP = (IP_last_state & ~0x20) | (state == ASSERT_LINE) ? 0x20 : 0;
// TODO: special mode for ip5
IP_last_state = newIP;
}
duart68681_channel *duartn68681_device::get_channel(int chan) duart68681_channel *duartn68681_device::get_channel(int chan)
{ {
if (chan == 0) if (chan == 0)

View File

@ -125,6 +125,14 @@ public:
devcb2_write8 write_outport; devcb2_write8 write_outport;
INT32 ip3clk, ip4clk, ip5clk, ip6clk; INT32 ip3clk, ip4clk, ip5clk, ip6clk;
// new-style push handlers for input port bits
DECLARE_WRITE_LINE_MEMBER( ip0_w );
DECLARE_WRITE_LINE_MEMBER( ip1_w );
DECLARE_WRITE_LINE_MEMBER( ip2_w );
DECLARE_WRITE_LINE_MEMBER( ip3_w );
DECLARE_WRITE_LINE_MEMBER( ip4_w );
DECLARE_WRITE_LINE_MEMBER( ip5_w );
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
@ -142,6 +150,7 @@ private:
UINT8 OPCR; /* Output Port Conf. Register */ UINT8 OPCR; /* Output Port Conf. Register */
UINT8 OPR; /* Output Port Register */ UINT8 OPR; /* Output Port Register */
PAIR CTR; /* Counter/Timer Preset Value */ PAIR CTR; /* Counter/Timer Preset Value */
UINT8 IPCR; /* Input Port Control Register */
/* state */ /* state */
UINT8 IP_last_state; /* last state of IP bits */ UINT8 IP_last_state; /* last state of IP bits */