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.cpp69
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: