summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mc68681.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mc68681.cpp')
-rw-r--r--src/devices/machine/mc68681.cpp122
1 files changed, 60 insertions, 62 deletions
diff --git a/src/devices/machine/mc68681.cpp b/src/devices/machine/mc68681.cpp
index 645b7c9deba..3a3fcfcecf7 100644
--- a/src/devices/machine/mc68681.cpp
+++ b/src/devices/machine/mc68681.cpp
@@ -112,8 +112,8 @@ DEFINE_DEVICE_TYPE(DUART_CHANNEL, duart_channel, "duart_channel", "DUART channel
// LIVE DEVICE
//**************************************************************************
-duart_base_device::duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock),
+duart_base_device::duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
m_chanA(*this, CHANA_TAG),
m_chanB(*this, CHANB_TAG),
m_chanC(*this, CHANC_TAG),
@@ -123,7 +123,7 @@ duart_base_device::duart_base_device(const machine_config &mconfig, device_type
write_b_tx(*this),
write_c_tx(*this),
write_d_tx(*this),
- read_inport(*this),
+ read_inport(*this, 0),
write_outport(*this),
ip3clk(0),
ip4clk(0),
@@ -200,15 +200,7 @@ void duart_base_device::set_clocks(int clk3, int clk4, int clk5, int clk6)
void duart_base_device::device_start()
{
- write_irq.resolve_safe();
- write_a_tx.resolve_safe();
- write_b_tx.resolve_safe();
- write_c_tx.resolve_safe();
- write_d_tx.resolve_safe();
- read_inport.resolve();
- write_outport.resolve_safe();
-
- duart_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(duart_base_device::duart_timer_callback),this), nullptr);
+ duart_timer = timer_alloc(FUNC(duart_base_device::duart_timer_callback), this);
save_item(NAME(ACR));
save_item(NAME(IMR));
@@ -622,7 +614,7 @@ uint8_t duart_base_device::read(offs_t offset)
break;
case 0x0d: /* IP */
- if (!read_inport.isnull())
+ if (!read_inport.isunset())
{
r = read_inport(); // TODO: go away
}
@@ -889,7 +881,7 @@ void duart_base_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(duart_base_device::ip0_w)
+void duart_base_device::ip0_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x01) | ((state == ASSERT_LINE) ? 1 : 0);
@@ -906,7 +898,7 @@ WRITE_LINE_MEMBER(duart_base_device::ip0_w)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip1_w)
+void duart_base_device::ip1_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x02) | ((state == ASSERT_LINE) ? 2 : 0);
@@ -923,7 +915,7 @@ WRITE_LINE_MEMBER(duart_base_device::ip1_w)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip2_w)
+void duart_base_device::ip2_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x04) | ((state == ASSERT_LINE) ? 4 : 0);
@@ -940,7 +932,7 @@ WRITE_LINE_MEMBER(duart_base_device::ip2_w)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip3_w)
+void duart_base_device::ip3_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x08) | ((state == ASSERT_LINE) ? 8 : 0);
@@ -957,21 +949,21 @@ WRITE_LINE_MEMBER(duart_base_device::ip3_w)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip4_w)
+void duart_base_device::ip4_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x10) | ((state == ASSERT_LINE) ? 0x10 : 0);
// TODO: special mode for ip4 (Ch. A Rx clock)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip5_w)
+void duart_base_device::ip5_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x20) | ((state == ASSERT_LINE) ? 0x20 : 0);
// TODO: special mode for ip5 (Ch. B Tx clock)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER(duart_base_device::ip6_w)
+void duart_base_device::ip6_w(int state)
{
uint8_t newIP = (IP_last_state & ~0x40) | ((state == ASSERT_LINE) ? 0x40 : 0);
// TODO: special mode for ip6 (Ch. B Rx clock)
@@ -1168,8 +1160,9 @@ duart_channel::duart_channel(const machine_config &mconfig, const char *tag, dev
, SR(0)
, rx_enabled(0)
, rx_fifo_num(0)
- , tx_enabled(0)
+ , m_tx_data_in_buffer(false)
, m_tx_break(false)
+ , m_bits_transmitted(255)
{
std::fill_n(&rx_fifo[0], MC68681_RX_FIFO_SIZE + 1, 0);
}
@@ -1192,10 +1185,10 @@ void duart_channel::device_start()
save_item(NAME(rx_fifo_read_ptr));
save_item(NAME(rx_fifo_write_ptr));
save_item(NAME(rx_fifo_num));
- save_item(NAME(tx_enabled));
- save_item(NAME(tx_data));
- save_item(NAME(tx_ready));
+ save_item(NAME(m_tx_data));
+ save_item(NAME(m_tx_data_in_buffer));
save_item(NAME(m_tx_break));
+ save_item(NAME(m_bits_transmitted));
}
void duart_channel::device_reset()
@@ -1267,20 +1260,17 @@ void duart_channel::rx_fifo_push(uint8_t data, uint8_t errors)
void duart_channel::tra_complete()
{
- //printf("%s ch %d Tx complete\n", tag(), m_ch);
- tx_ready = 1;
- SR |= STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY;
-
- if (m_ch == 0)
- m_uart->set_ISR_bits(INT_TXRDYA);
+ if (!(SR & STATUS_TRANSMITTER_READY))
+ {
+ transmit_register_setup(m_tx_data);
+ m_bits_transmitted = 0;
+ m_tx_data_in_buffer = false;
+ }
else
- m_uart->set_ISR_bits(INT_TXRDYB);
-
- // if local loopback is on, write the transmitted data as if a byte had been received
- if ((MR2 & 0xc0) == 0x80)
- rx_fifo_push(tx_data, 0);
-
- update_interrupts();
+ {
+ SR |= STATUS_TRANSMITTER_EMPTY;
+ update_interrupts();
+ }
}
void duart_channel::tra_callback()
@@ -1307,9 +1297,15 @@ void duart_channel::tra_callback()
m_uart->write_d_tx(bit);
}
}
- else // must call this to advance the transmitter
+ else
+ // loop back transmitted bit
+ rx_w(transmit_register_get_data_bit());
+
+ // TxRDY is not set until the end of start bit time
+ if (++m_bits_transmitted > 1 && !m_tx_data_in_buffer)
{
- transmit_register_get_data_bit();
+ SR |= STATUS_TRANSMITTER_READY;
+ update_interrupts();
}
}
@@ -1559,14 +1555,20 @@ void duart_channel::write_CR(uint8_t data)
receive_register_reset();
break;
case 3: /* Reset channel transmitter */
- tx_enabled = 0;
- tx_ready = 0;
SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
if (m_ch == 0)
+ {
+ m_uart->write_a_tx(1);
m_uart->clear_ISR_bits(INT_TXRDYA);
+ }
else
+ {
+ m_uart->write_b_tx(1);
m_uart->clear_ISR_bits(INT_TXRDYB);
+ }
transmit_register_reset();
+ m_bits_transmitted = 255;
+ m_tx_data_in_buffer = false;
break;
case 4: /* Reset Error Status */
SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR | STATUS_OVERRUN_ERROR);
@@ -1622,11 +1624,10 @@ void duart_channel::write_CR(uint8_t data)
SR &= ~STATUS_RECEIVER_READY;
}
- if (!tx_enabled && BIT(data, 2))
+ if (!(SR & STATUS_TRANSMITTER_READY) && BIT(data, 2))
{
- tx_enabled = 1;
- tx_ready = 1;
SR |= STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY;
+ m_tx_data_in_buffer = false;
if (m_ch == 0)
m_uart->set_ISR_bits(INT_TXRDYA);
else
@@ -1634,9 +1635,8 @@ void duart_channel::write_CR(uint8_t data)
}
if (BIT(data, 3))
{
- tx_enabled = 0;
- tx_ready = 0;
SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
+ m_tx_data_in_buffer = false;
if (m_ch == 0)
m_uart->clear_ISR_bits(INT_TXRDYA);
else
@@ -1648,25 +1648,23 @@ void duart_channel::write_CR(uint8_t data)
void duart_channel::write_TX(uint8_t data)
{
- tx_data = data;
-
-/* if (!tx_ready)
- {
- printf("Write %02x to TX when TX not ready!\n", data);
- }*/
-
- //printf("%s ch %d Tx %c [%02x]\n", tag(), m_ch, isprint(data) ? data : ' ', data);
+ if (!(SR & STATUS_TRANSMITTER_READY))
+ {
+ logerror("write_tx transmitter not ready (data 0x%02x discarded)\n", data);
+ return;
+ }
- tx_ready = 0;
SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
-
- if (m_ch == 0)
- m_uart->clear_ISR_bits(INT_TXRDYA);
+ if (!is_transmit_register_empty())
+ {
+ m_tx_data = data;
+ m_tx_data_in_buffer = true;
+ }
else
- m_uart->clear_ISR_bits(INT_TXRDYB);
-
- // send tx_data
- transmit_register_setup(tx_data);
+ {
+ transmit_register_setup(data);
+ m_bits_transmitted = 0;
+ }
update_interrupts();
}