z80scc: serial control signal fixes

* /CTS, /DCD and /SYNC are active low lines represented as 1's in rr0 when asserted
* immediately deassert /RTS in some circumstances
* fix rr1 "all sent" status handling
* there is no ring indicator input line
* generate interrupts for /SYNC input
This commit is contained in:
Patrick Mackinlay 2018-08-09 14:10:18 +07:00
parent 075ddba239
commit d7eea22d29
2 changed files with 37 additions and 22 deletions

View File

@ -1459,13 +1459,15 @@ void z80scc_channel::update_rts()
if (m_wr5 & WR5_RTS) if (m_wr5 & WR5_RTS)
{ {
// when the RTS bit is set, the _RTS output goes low // when the RTS bit is set, the _RTS output goes low
set_rts(0);
m_rts = 1; m_rts = 1;
set_rts(!m_rts);
} }
else else
{ {
// when the RTS bit is reset, the _RTS output goes high after the transmitter empties // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
m_rts = 0; m_rts = 0;
if (!(m_wr3 & WR3_AUTO_ENABLES) || (m_rr1 & RR1_ALL_SENT))
set_rts(!m_rts);
} }
// data terminal ready output follows the state programmed into the DTR bit*/ // data terminal ready output follows the state programmed into the DTR bit*/
@ -2621,8 +2623,6 @@ void z80scc_channel::data_write(uint8_t data)
LOGTX("- TX FIFO has more room, setting TBE bit\n"); LOGTX("- TX FIFO has more room, setting TBE bit\n");
m_rr0 |= RR0_TX_BUFFER_EMPTY; // or there is a slot in the FIFO available m_rr0 |= RR0_TX_BUFFER_EMPTY; // or there is a slot in the FIFO available
} }
LOGTX("- TX FIFO now has data to send, clearing ALL_SENT bit\n");
m_rr1 &= ~RR1_ALL_SENT; // All is definitelly not sent anymore
} }
check_waitrequest(); check_waitrequest();
@ -2636,7 +2636,8 @@ void z80scc_channel::data_write(uint8_t data)
LOGTX("- Setting up transmitter\n"); LOGTX("- Setting up transmitter\n");
transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Load the shift register, reload is done in tra_complete() transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Load the shift register, reload is done in tra_complete()
m_tx_fifo_rp_step(); m_tx_fifo_rp_step();
m_rr1 |= RR1_ALL_SENT; // Now stuff is on its way again LOGTX("- TX shift register loaded, clearing ALL_SENT bit\n");
m_rr1 &= ~RR1_ALL_SENT; // All is definitely not sent anymore
m_rr0 |= RR0_TX_BUFFER_EMPTY; // And there is a slot in the FIFO available m_rr0 |= RR0_TX_BUFFER_EMPTY; // And there is a slot in the FIFO available
} }
else else
@ -2730,7 +2731,7 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
{ {
LOG("\"%s\"%s: %c : CTS %u\n", owner()->tag(), FUNCNAME, 'A' + m_index, state); LOG("\"%s\"%s: %c : CTS %u\n", owner()->tag(), FUNCNAME, 'A' + m_index, state);
if ((m_rr0 & RR0_CTS) != (state ? RR0_CTS : 0)) // SCC change detection logic if ((m_rr0 & RR0_CTS) != (state ? 0 : RR0_CTS)) // SCC change detection logic
{ {
// enable transmitter if in auto enables mode // enable transmitter if in auto enables mode
if (!state) if (!state)
@ -2743,7 +2744,7 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
} }
} }
if (state) m_rr0 |= RR0_CTS; else m_rr0 &= ~RR0_CTS; // Raw pin/status value if (state) m_rr0 &= ~RR0_CTS; else m_rr0 |= RR0_CTS; // Raw pin/status value
if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_CTS)) if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_CTS))
{ {
@ -2767,7 +2768,7 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
{ {
LOGDCD("\"%s\": %c : DCD %u\n", owner()->tag(), 'A' + m_index, state); LOGDCD("\"%s\": %c : DCD %u\n", owner()->tag(), 'A' + m_index, state);
if ((m_rr0 & RR0_DCD) != (state ? RR0_DCD : 0)) // SCC change detection logic if ((m_rr0 & RR0_DCD) != (state ? 0 : RR0_DCD)) // SCC change detection logic
{ {
// enable transmitter if in auto enables mode // enable transmitter if in auto enables mode
if (!state) if (!state)
@ -2783,7 +2784,7 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
} }
} }
if (state) m_rr0 |= RR0_DCD; else m_rr0 &= ~RR0_DCD; // Raw pin/status value if (state) m_rr0 &= ~RR0_DCD; else m_rr0 |= RR0_DCD; // Raw pin/status value
if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_DCD)) if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_DCD))
{ {
@ -2799,25 +2800,42 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
} }
} }
//-------------------------------------------------
// ri_w - ring indicator handler
//-------------------------------------------------
WRITE_LINE_MEMBER( z80scc_channel::ri_w )
{
LOGINT("\"%s\": %c : RI %u - not implemented\n", owner()->tag(), 'A' + m_index, state);
}
//------------------------------------------------- //-------------------------------------------------
// sync_w - sync handler for external sync mode // sync_w - sync handler for external sync mode
//------------------------------------------------- //-------------------------------------------------
WRITE_LINE_MEMBER( z80scc_channel::sync_w ) WRITE_LINE_MEMBER( z80scc_channel::sync_w )
{ {
LOGSYNC("\"%s\": %c : SYNC %u\n", owner()->tag(), 'A' + m_index, state); LOGSYNC("\"%s\": %c : SYNC %u\n", owner()->tag(), 'A' + m_index, state);
if ((m_rr0 & RR0_SYNC_HUNT) != (state ? RR0_SYNC_HUNT : 0)) // SCC change detection logic
/*
* The /SYNC pin is a general purpose input whose state is reported in the
* Sync/Hunt bit in RR0. If the crystal oscillator is enabled, this pin is
* not available and the Sync/Hunt bit is forced to 0. Otherwise, the /SYNC
* pin may be used to carry the Ring Indicator signal.
*/
if (!(m_wr11 & WR11_RCVCLK_TYPE))
{ {
if (state) m_rr0 |= RR0_SYNC_HUNT; else m_rr0 &= ~RR0_SYNC_HUNT; // Raw pin/status value // check for state change
if ((m_rr0 & RR0_SYNC_HUNT) != (state ? 0 : RR0_SYNC_HUNT))
{
// record pin state (inverted)
if (state)
m_rr0 &= ~RR0_SYNC_HUNT;
else
m_rr0 |= RR0_SYNC_HUNT;
// trigger an external interrupt if enabled
if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_SYNC))
{
m_extint_latch = 1;
m_extint_states = m_rr0;
m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
}
}
} }
else
fatalerror("/SYNC cannot be used as an input in RTxC-XTAL clock mode.");
} }
//------------------------------------------------- //-------------------------------------------------

View File

@ -176,7 +176,6 @@ public:
DECLARE_WRITE_LINE_MEMBER( write_rx ); DECLARE_WRITE_LINE_MEMBER( write_rx );
DECLARE_WRITE_LINE_MEMBER( cts_w ); DECLARE_WRITE_LINE_MEMBER( cts_w );
DECLARE_WRITE_LINE_MEMBER( dcd_w ); DECLARE_WRITE_LINE_MEMBER( dcd_w );
DECLARE_WRITE_LINE_MEMBER( ri_w );
DECLARE_WRITE_LINE_MEMBER( rxc_w ); DECLARE_WRITE_LINE_MEMBER( rxc_w );
DECLARE_WRITE_LINE_MEMBER( txc_w ); DECLARE_WRITE_LINE_MEMBER( txc_w );
DECLARE_WRITE_LINE_MEMBER( sync_w ); DECLARE_WRITE_LINE_MEMBER( sync_w );
@ -449,8 +448,6 @@ public:
DECLARE_WRITE_LINE_MEMBER( ctsb_w ) { m_chanB->cts_w(state); } DECLARE_WRITE_LINE_MEMBER( ctsb_w ) { m_chanB->cts_w(state); }
DECLARE_WRITE_LINE_MEMBER( dcda_w ) { m_chanA->dcd_w(state); } DECLARE_WRITE_LINE_MEMBER( dcda_w ) { m_chanA->dcd_w(state); }
DECLARE_WRITE_LINE_MEMBER( dcdb_w ) { m_chanB->dcd_w(state); } DECLARE_WRITE_LINE_MEMBER( dcdb_w ) { m_chanB->dcd_w(state); }
DECLARE_WRITE_LINE_MEMBER( ria_w ) { m_chanA->ri_w(state); }
DECLARE_WRITE_LINE_MEMBER( rib_w ) { m_chanB->ri_w(state); }
DECLARE_WRITE_LINE_MEMBER( rxca_w ) { m_chanA->rxc_w(state); } DECLARE_WRITE_LINE_MEMBER( rxca_w ) { m_chanA->rxc_w(state); }
DECLARE_WRITE_LINE_MEMBER( rxcb_w ) { m_chanB->rxc_w(state); } DECLARE_WRITE_LINE_MEMBER( rxcb_w ) { m_chanB->rxc_w(state); }
DECLARE_WRITE_LINE_MEMBER( txca_w ) { m_chanA->txc_w(state); } DECLARE_WRITE_LINE_MEMBER( txca_w ) { m_chanA->txc_w(state); }