diff options
Diffstat (limited to 'src/devices/machine/6850acia.cpp')
-rw-r--r-- | src/devices/machine/6850acia.cpp | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/src/devices/machine/6850acia.cpp b/src/devices/machine/6850acia.cpp index b7a7de81e4b..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 @@ -16,10 +16,15 @@ MACROS ***************************************************************************/ -//#define VERBOSE 1 +#define LOG_SETUP (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_SETUP) //#define LOG_OUTPUT_STREAM std::cout + #include "logmacro.h" +#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) + /*************************************************************************** LOCAL VARIABLES ***************************************************************************/ @@ -87,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) { } @@ -101,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)); @@ -154,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; @@ -177,12 +180,14 @@ void acia6850_device::control_w(uint8_t data) // CR0 & CR1 int counter_divide_select_bits = (data >> 0) & 3; m_divide = counter_divide_select[counter_divide_select_bits]; + LOGSETUP(" - Divide: x%d\n", counter_divide_select[counter_divide_select_bits]); // CR2, CR3 & CR4 int word_select_bits = (data >> 2) & 7; m_bits = word_select[word_select_bits][0]; m_parity = word_select[word_select_bits][1]; m_stopbits = word_select[word_select_bits][2]; + LOGSETUP(" - %d%c%d\n", m_bits, m_parity == PARITY_NONE ? 'N' : (m_parity == PARITY_ODD ? 'O' : 'E'), m_stopbits); // CR5 & CR6 int transmitter_control_bits = (data >> 5) & 3; @@ -192,6 +197,7 @@ void acia6850_device::control_w(uint8_t data) // CR7 m_rx_irq_enable = (data >> 7) & 1; + LOGSETUP(" - RTS:%d BRK:%d TxIE:%d RxIE:%d\n", rts, m_brk, m_tx_irq_enable, m_rx_irq_enable); if (m_divide == 0) { @@ -211,7 +217,14 @@ void acia6850_device::control_w(uint8_t data) m_tx_state = STATE_START; output_txd(1); - m_status &= SR_CTS; + // 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) { @@ -227,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() @@ -244,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 if (m_divide == 0) { - logerror("%s:ACIA %p: Data write while in reset!\n", machine().describe_context(), (void *)this); + 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 what happens 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(); } @@ -296,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) { @@ -308,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) { @@ -461,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) { @@ -476,7 +494,6 @@ WRITE_LINE_MEMBER( acia6850_device::write_txc ) { m_tx_counter++; - /// TODO: check txd is correctly generated, check atarist mcu is reading data, start checking receive data. switch (m_tx_state) { case STATE_START: |