diff options
Diffstat (limited to 'src/devices/machine/6850acia.cpp')
-rw-r--r-- | src/devices/machine/6850acia.cpp | 57 |
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) { |