diff options
Diffstat (limited to 'src/devices/machine/mc68681.cpp')
-rw-r--r-- | src/devices/machine/mc68681.cpp | 122 |
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(); } |