summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80scc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/z80scc.cpp')
-rw-r--r--src/devices/machine/z80scc.cpp83
1 files changed, 58 insertions, 25 deletions
diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp
index 83fd4f8c3e5..7c999df4ac9 100644
--- a/src/devices/machine/z80scc.cpp
+++ b/src/devices/machine/z80scc.cpp
@@ -374,7 +374,7 @@ DEFINE_DEVICE_TYPE(Z80SCC_CHANNEL, z80scc_channel, "z80scc_channel", "Z80 SCC C
DEFINE_DEVICE_TYPE(SCC8030, scc8030_device, "scc8030", "Zilog Z8030 SCC")
DEFINE_DEVICE_TYPE(SCC80C30, scc80c30_device, "scc80c30", "Zilog Z80C30 SCC")
DEFINE_DEVICE_TYPE(SCC80230, scc80230_device, "scc80230", "Zilog Z80230 ESCC")
-DEFINE_DEVICE_TYPE(SCC8530N, scc8530_device, "scc8530", "Zilog Z8530 SCC") // remove trailing N when 8530scc.c is fully replaced and removed
+DEFINE_DEVICE_TYPE(SCC8530, scc8530_device, "scc8530", "Zilog Z8530 SCC")
DEFINE_DEVICE_TYPE(SCC85C30, scc85c30_device, "scc85c30", "Zilog Z85C30 SCC")
DEFINE_DEVICE_TYPE(SCC85230, scc85230_device, "scc85230", "Zilog Z85230 ESCC")
DEFINE_DEVICE_TYPE(SCC85233, scc85233_device, "scc85233", "Zilog Z85233 EMSCC")
@@ -455,7 +455,7 @@ scc80230_device::scc80230_device(const machine_config &mconfig, const char *tag,
}
scc8530_device::scc8530_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : z80scc_device(mconfig, SCC8530N, tag, owner, clock, TYPE_SCC8530)
+ : z80scc_device(mconfig, SCC8530, tag, owner, clock, TYPE_SCC8530)
{
}
@@ -1796,6 +1796,8 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
break;
}
}
+ // re-assert interrupt if conditions are still present
+ check_receive_interrupt();
break;
case WR0_ERROR_RESET:
/*Error Reset Command (110). This command resets the error bits in RR1. If interrupt on first Rx
@@ -2092,7 +2094,7 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
/RTxC pin.*/
switch (data & WR11_RCVCLK_SRC_MASK)
{
- case WR11_RCVCLK_SRC_RTXC: LOG("Receive clock source is RTxC - not implemented\n"); break;
+ case WR11_RCVCLK_SRC_RTXC: LOG("Receive clock source is RTxC\n"); break;
case WR11_RCVCLK_SRC_TRXC: LOG("Receive clock source is TRxC - not implemented\n"); break;
case WR11_RCVCLK_SRC_BR: LOG("Receive clock source is Baudrate Generator\n"); break;
case WR11_RCVCLK_SRC_DPLL: LOG("Receive clock source is DPLL - not implemented\n"); break;
@@ -2106,7 +2108,7 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
source of the transmit clocks.*/
switch (data & WR11_TRACLK_SRC_MASK)
{
- case WR11_TRACLK_SRC_RTXC: LOG("Transmit clock source is RTxC - not implemented\n"); break;
+ case WR11_TRACLK_SRC_RTXC: LOG("Transmit clock source is RTxC\n"); break;
case WR11_TRACLK_SRC_TRXC: LOG("Transmit clock source is TRxC - not implemented\n"); break;
case WR11_TRACLK_SRC_BR: LOG("Transmit clock source is Baudrate Generator\n"); break;
case WR11_TRACLK_SRC_DPLL: LOG("Transmit clock source is DPLL - not implemented\n"); break;
@@ -2136,6 +2138,8 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
}
else
LOG("TRxC pin is Input\n");
+
+ update_serial();
}
/*WR12 contains the lower byte of the time constant for the baud rate generator. The time constant
@@ -2582,22 +2586,7 @@ void z80scc_channel::receive_data(uint8_t data)
m_rr0 |= RR0_RX_CHAR_AVAILABLE;
check_dma_request();
- // receive interrupt on FIRST and ALL character
- switch (m_wr1 & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_FIRST:
- if (m_rx_first)
- {
- m_uart->trigger_interrupt(m_index, INT_RECEIVE);
-
- m_rx_first = 0;
- }
- break;
-
- case WR1_RX_INT_ALL:
- m_uart->trigger_interrupt(m_index, INT_RECEIVE);
- break;
- }
+ check_receive_interrupt();
}
@@ -2795,18 +2784,30 @@ unsigned int z80scc_channel::get_brg_rate()
if (m_wr14 & WR14_BRG_SOURCE) // Do we use the PCLK as baudrate source
{
rate = owner()->clock() / (brg_const == 0 ? 1 : brg_const);
- LOG(" - Source bit rate (%d) = PCLK (%d) / (%d)\n", rate, owner()->clock(), brg_const);
+ LOG(" - BRG Source bit rate (%d) = PCLK (%d) / (%d)\n", rate, owner()->clock(), brg_const);
}
else // Else we use the RTxC as BRG source
{
unsigned int source = (m_index == z80scc_device::CHANNEL_A) ? m_uart->m_rxca : m_uart->m_rxcb;
rate = source / (brg_const == 0 ? 1 : brg_const);
- LOG(" - Source bit rate (%d) = RTxC (%d) / (%d)\n", rate, source, brg_const);
+ LOG(" - BRG Source bit rate (%d) = RTxC (%d) / (%d)\n", rate, source, brg_const);
}
return (rate / (2 * get_clock_mode()));
}
+//-------------------------------------------------
+// get_rtxc_rate
+//-------------------------------------------------
+unsigned int z80scc_channel::get_rtxc_rate()
+{
+ unsigned int rate;
+ unsigned int source = (m_index == z80scc_device::CHANNEL_A) ? m_uart->m_rxca : m_uart->m_rxcb;
+ rate = source / get_clock_mode();
+ LOG(" - RTxC Source bit rate (%d) = RTxC (%d) / (%d)\n", rate, source, get_clock_mode());
+ return rate;
+}
+
void z80scc_channel::update_baudtimer()
{
unsigned int rate;
@@ -2893,9 +2894,20 @@ void z80scc_channel::update_serial()
}
else
{
- LOG("- BRG disabled\n");
- set_rcv_rate(0);
- set_tra_rate(0);
+ if ((m_wr11 & WR11_RCVCLK_SRC_MASK) == WR11_RCVCLK_SRC_RTXC &&
+ (m_wr11 & WR11_TRACLK_SRC_MASK) == WR11_TRACLK_SRC_RTXC)
+ {
+ m_brg_rate = get_rtxc_rate();
+ LOG("- BRG disabled, clock source RTxC (rate %d, clock %d)\n", m_brg_rate, get_clock_mode());
+ set_rcv_rate(m_brg_rate);
+ set_tra_rate(m_brg_rate);
+ }
+ else
+ {
+ LOG("- BRG disabled and RX/TX clock sources differ, unimplemented: stopping\n");
+ set_rcv_rate(0);
+ set_tra_rate(0);
+ }
}
// TODO: Check registers for use of RTxC and TRxC, if used as direct Tx and/or Rx clocks set them to value as programmed
// in m_uart->txca/txcb and rxca/rxcb respectivelly
@@ -2980,3 +2992,24 @@ void z80scc_channel::check_dma_request()
}
}
}
+
+void z80scc_channel::check_receive_interrupt()
+{
+ if (m_rr0 & RR0_RX_CHAR_AVAILABLE)
+ {
+ switch (m_wr1 & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (m_rx_first)
+ {
+ m_uart->trigger_interrupt(m_index, INT_RECEIVE);
+ m_rx_first = 0;
+ }
+ break;
+
+ case WR1_RX_INT_ALL:
+ m_uart->trigger_interrupt(m_index, INT_RECEIVE);
+ break;
+ }
+ }
+}