summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/6850acia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/6850acia.cpp')
-rw-r--r--src/devices/machine/6850acia.cpp57
1 files changed, 32 insertions, 25 deletions
diff --git a/src/devices/machine/6850acia.cpp b/src/devices/machine/6850acia.cpp
index efd557daff1..625f5ba67b5 100644
--- a/src/devices/machine/6850acia.cpp
+++ b/src/devices/machine/6850acia.cpp
@@ -2,7 +2,7 @@
// copyright-holders:smf
/*********************************************************************
- 6850acia.c
+ 6850acia.cpp
6850 ACIA code
@@ -92,10 +92,13 @@ acia6850_device::acia6850_device(const machine_config &mconfig, device_type type
, m_irq(0)
, m_txc(0)
, m_txd(0)
+ , m_tx_state(0)
, m_tx_counter(0)
, m_tx_irq_enable(false)
, m_rxc(0)
, m_rxd(1)
+ , m_rx_state(0)
+ , m_rx_counter(0)
, m_rx_irq_enable(false)
{
}
@@ -106,11 +109,6 @@ acia6850_device::acia6850_device(const machine_config &mconfig, device_type type
void acia6850_device::device_start()
{
- // resolve callbacks
- m_txd_handler.resolve_safe();
- m_rts_handler.resolve_safe();
- m_irq_handler.resolve_safe();
-
save_item(NAME(m_status));
save_item(NAME(m_tdr));
save_item(NAME(m_rdr));
@@ -159,13 +157,13 @@ uint8_t acia6850_device::status_r()
{
uint8_t status = m_status;
- if (!machine().side_effects_disabled())
+ if (m_divide == 0 || (status & SR_CTS))
{
- if (status & SR_CTS)
- {
- status &= ~SR_TDRE;
- }
+ status &= ~SR_TDRE;
+ }
+ if (!machine().side_effects_disabled())
+ {
if (m_dcd_irq_pending == DCD_IRQ_READ_STATUS)
{
m_dcd_irq_pending = DCD_IRQ_READ_DATA;
@@ -219,9 +217,13 @@ void acia6850_device::control_w(uint8_t data)
m_tx_state = STATE_START;
output_txd(1);
- /// TODO: find out whether this has any immediate effect on TDRE
- /// TDRE probably shouldn't be cleared here if TDR wasn't loaded, despite what the datasheet implies
- /// If TDRE is cleared, then a separate internal flag is needed to avoid transmitting a spurious first character
+ // TDRE flag reads as zero in this reset state, but the drivers
+ // internal SR_TDRE is masked elsewhere when in the reset
+ // state. When taken out of reset the TDRE flag reads as one.
+ m_status |= SR_TDRE;
+
+ // SR_CTS is not affected by a reset, it should still reflect
+ // the pin status.
m_status &= SR_CTS | SR_TDRE;
if (m_dcd)
@@ -238,12 +240,12 @@ void acia6850_device::control_w(uint8_t data)
int acia6850_device::calculate_txirq()
{
- return !(m_tx_irq_enable && ((m_status & SR_TDRE) && !(m_status & SR_CTS)));
+ return !(m_tx_irq_enable && m_divide && (m_status & SR_TDRE) && !(m_status & SR_CTS));
}
int acia6850_device::calculate_rxirq()
{
- return !(m_rx_irq_enable && ((m_status & SR_RDRF) || m_dcd_irq_pending != DCD_IRQ_NONE));
+ return !(m_rx_irq_enable && m_divide && ((m_status & SR_RDRF) || m_dcd_irq_pending != DCD_IRQ_NONE));
}
void acia6850_device::update_irq()
@@ -255,15 +257,20 @@ void acia6850_device::data_w(uint8_t data)
{
LOG("MC6850 '%s' Data: %02x\n", tag(), data);
- /// TODO: find out if data stored during master reset is sent after divider is set (and if TDRE can be cleared by such a write)
if (m_divide == 0)
{
logerror("%s: ACIA data write while in reset!\n", machine().describe_context());
}
+ else
+ {
+ // TDRE reads as set when taken out of reset even if data is
+ // written while in reset.
- /// TODO: find out whether this overwrites previous data or has no effect if TDRE is already clear when you write
- m_tdr = data;
- m_status &= ~SR_TDRE;
+ // TODO: find out whether this overwrites previous data or has
+ // no effect if TDRE is already clear when you write?
+ m_tdr = data;
+ m_status &= ~SR_TDRE;
+ }
update_irq();
}
@@ -307,7 +314,7 @@ uint8_t acia6850_device::read(offs_t offset)
return BIT(offset, 0) ? data_r() : status_r();
}
-DECLARE_WRITE_LINE_MEMBER( acia6850_device::write_cts )
+void acia6850_device::write_cts(int state)
{
if (state)
{
@@ -319,12 +326,12 @@ DECLARE_WRITE_LINE_MEMBER( acia6850_device::write_cts )
}
}
-DECLARE_WRITE_LINE_MEMBER( acia6850_device::write_dcd )
+void acia6850_device::write_dcd(int state)
{
m_dcd = state;
}
-WRITE_LINE_MEMBER( acia6850_device::write_rxc )
+void acia6850_device::write_rxc(int state)
{
if (m_rxc != state)
{
@@ -472,12 +479,12 @@ WRITE_LINE_MEMBER( acia6850_device::write_rxc )
}
}
-DECLARE_WRITE_LINE_MEMBER( acia6850_device::write_rxd )
+void acia6850_device::write_rxd(int state)
{
m_rxd = state;
}
-WRITE_LINE_MEMBER( acia6850_device::write_txc )
+void acia6850_device::write_txc(int state)
{
if (m_txc != state)
{