summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80dart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/z80dart.cpp')
-rw-r--r--src/devices/machine/z80dart.cpp1270
1 files changed, 0 insertions, 1270 deletions
diff --git a/src/devices/machine/z80dart.cpp b/src/devices/machine/z80dart.cpp
deleted file mode 100644
index a5f80551712..00000000000
--- a/src/devices/machine/z80dart.cpp
+++ /dev/null
@@ -1,1270 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Curt Coder
-/***************************************************************************
-
- Z80-DART Dual Asynchronous Receiver/Transmitter emulation
-
- The z80dart/z80sio itself is based on an older intel serial chip, the i8274 MPSC
- (see http://doc.chipfind.ru/pdf/intel/8274.pdf), which also has almost identical
- behavior, except lacks the interrupt daisy chaining and has its own interrupt/dma
- scheme which uses write register 2 on channel A, that register which is unused on
- the z80dart and z80sio.
-
-***************************************************************************/
-
-/*
-
- TODO:
-
- - i8274 DMA scheme
- - break detection
- - wr0 reset tx interrupt pending
- - wait/ready
- - 1.5 stop bits
-
-*/
-
-#include "emu.h"
-#include "z80dart.h"
-
-//#define VERBOSE 1
-//#define LOG_OUTPUT_FUNC printf
-#include "logmacro.h"
-
-#define CHANA_TAG "cha"
-#define CHANB_TAG "chb"
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-// device type definition
-DEFINE_DEVICE_TYPE(Z80DART, z80dart_device, "z80dart", "Z80 DART")
-DEFINE_DEVICE_TYPE(Z80DART_CHANNEL, z80dart_channel, "z80dart_channel", "Z80 DART channel")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void z80dart_device::device_add_mconfig(machine_config &config)
-{
- Z80DART_CHANNEL(config, m_chanA, 0);
- Z80DART_CHANNEL(config, m_chanB, 0);
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// z80dart_device - constructor
-//-------------------------------------------------
-
-z80dart_device::z80dart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant)
- : device_t(mconfig, type, tag, owner, clock)
- , device_z80daisy_interface(mconfig, *this)
- , m_chanA(*this, CHANA_TAG)
- , m_chanB(*this, CHANB_TAG)
- , m_rxca(0)
- , m_txca(0)
- , m_rxcb(0)
- , m_txcb(0)
- , m_out_txda_cb(*this)
- , m_out_dtra_cb(*this)
- , m_out_rtsa_cb(*this)
- , m_out_wrdya_cb(*this)
- , m_out_synca_cb(*this)
- , m_out_txdb_cb(*this)
- , m_out_dtrb_cb(*this)
- , m_out_rtsb_cb(*this)
- , m_out_wrdyb_cb(*this)
- , m_out_syncb_cb(*this)
- , m_out_int_cb(*this)
- , m_out_rxdrqa_cb(*this)
- , m_out_txdrqa_cb(*this)
- , m_out_rxdrqb_cb(*this)
- , m_out_txdrqb_cb(*this)
- , m_variant(variant)
-{
- for (auto & elem : m_int_state)
- elem = 0;
-}
-
-z80dart_device::z80dart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : z80dart_device(mconfig, Z80DART, tag, owner, clock, TYPE_DART)
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void z80dart_device::device_start()
-{
- // resolve callbacks
- m_out_txda_cb.resolve_safe();
- m_out_dtra_cb.resolve_safe();
- m_out_rtsa_cb.resolve_safe();
- m_out_wrdya_cb.resolve_safe();
- m_out_synca_cb.resolve_safe();
- m_out_txdb_cb.resolve_safe();
- m_out_dtrb_cb.resolve_safe();
- m_out_rtsb_cb.resolve_safe();
- m_out_wrdyb_cb.resolve_safe();
- m_out_syncb_cb.resolve_safe();
- m_out_int_cb.resolve_safe();
- m_out_rxdrqa_cb.resolve_safe();
- m_out_txdrqa_cb.resolve_safe();
- m_out_rxdrqb_cb.resolve_safe();
- m_out_txdrqb_cb.resolve_safe();
-
- // configure channel A
- m_chanA->set_rxc(m_rxca);
- m_chanA->set_txc(m_txca);
-
- // configure channel B
- m_chanB->set_rxc(m_rxcb);
- m_chanB->set_txc(m_txcb);
-
- // state saving
- save_item(NAME(m_int_state));
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void z80dart_device::device_reset()
-{
- LOG("Z80DART \"%s\" Reset\n", tag());
-}
-
-//-------------------------------------------------
-// z80daisy_irq_state - get interrupt status
-//-------------------------------------------------
-
-int z80dart_device::z80daisy_irq_state()
-{
- int state = 0;
- int i;
-
- LOG("Z80DART \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
- m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
- m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]);
-
- // loop over all interrupt sources
- for (i = 0; i < 8; i++)
- {
- // if we're servicing a request, don't indicate more interrupts
- if (m_int_state[i] & Z80_DAISY_IEO)
- {
- state |= Z80_DAISY_IEO;
- break;
- }
- state |= m_int_state[i];
- }
-
- LOG("Z80DART \"%s\" : Interrupt State %u\n", tag(), state);
-
- return state;
-}
-
-
-//-------------------------------------------------
-// z80daisy_irq_ack - interrupt acknowledge
-//-------------------------------------------------
-
-int z80dart_device::z80daisy_irq_ack()
-{
- int i;
-
- LOG("Z80DART \"%s\" Interrupt Acknowledge\n", tag());
-
- // loop over all interrupt sources
- for (i = 0; i < 8; i++)
- {
- // find the first channel with an interrupt requested
- if (m_int_state[i] & Z80_DAISY_INT)
- {
- // clear interrupt, switch to the IEO state, and update the IRQs
- m_int_state[i] = Z80_DAISY_IEO;
- m_chanA->clr_interrupt_pending();
- check_interrupts();
-
- LOG("Z80DART \"%s\" : Interrupt Acknowledge Vector %02x\n", tag(), m_chanB->get_vector());
-
- return m_chanB->get_vector();
- }
- }
-
- //logerror("z80dart_irq_ack: failed to find an interrupt to ack!\n");
-
- return m_chanB->get_vector();
-}
-
-
-//-------------------------------------------------
-// z80daisy_irq_reti - return from interrupt
-//-------------------------------------------------
-
-void z80dart_device::z80daisy_irq_reti()
-{
- int i;
-
- LOG("Z80DART \"%s\" Return from Interrupt\n", tag());
-
- // loop over all interrupt sources
- for (i = 0; i < 8; i++)
- {
- // find the first channel with an IEO pending
- if (m_int_state[i] & Z80_DAISY_IEO)
- {
- // clear the IEO state and update the IRQs
- m_int_state[i] &= ~Z80_DAISY_IEO;
- check_interrupts();
- return;
- }
- }
-
- //logerror("z80dart_irq_reti: failed to find an interrupt to clear IEO on!\n");
-}
-
-
-//-------------------------------------------------
-// check_interrupts -
-//-------------------------------------------------
-
-void z80dart_device::check_interrupts()
-{
- int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
- m_out_int_cb(state);
-}
-
-
-//-------------------------------------------------
-// reset_interrupts -
-//-------------------------------------------------
-
-void z80dart_device::reset_interrupts()
-{
- for (auto & elem : m_int_state)
- {
- elem = 0;
- }
-
- check_interrupts();
-}
-
-
-//-------------------------------------------------
-// trigger_interrupt -
-//-------------------------------------------------
-
-void z80dart_device::trigger_interrupt(int index, int state)
-{
- uint8_t vector = m_chanB->m_wr[2];
- int priority;
-
- if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201))
- {
- int prio_level = 0;
- switch(state)
- {
- case z80dart_channel::INT_TRANSMIT:
- prio_level = 1;
- break;
- case z80dart_channel::INT_RECEIVE:
- case z80dart_channel::INT_SPECIAL:
- prio_level = 0;
- break;
- case z80dart_channel::INT_EXTERNAL:
- prio_level = 2;
- break;
- }
-
- if(m_chanA->get_priority())
- {
- priority = (prio_level * 2) + index;
- }
- else
- {
- priority = (prio_level == 2) ? index + 4 : ((index * 2) + prio_level);
- }
- if (m_chanB->get_status_vector())
- {
- vector = (!index << 2) | state;
- if((m_chanA->m_wr[1] & 0x18) == z80dart_channel::WR2_MODE_8086_8088)
- {
- vector = (m_chanB->m_wr[2] & 0xf8) | vector;
- }
- else
- {
- vector = (m_chanB->m_wr[2] & 0xe3) | (vector << 2);
- }
- }
- }
- else
- {
- priority = (index << 2) | state;
- if (m_chanB->get_status_vector())
- {
- // status affects vector
- vector = (m_chanB->m_wr[2] & 0xf1) | (!index << 3) | (state << 1);
- }
- }
-
- LOG("Z80DART \"%s\" Channel %c : Interrupt Request %u\n", tag(), 'A' + index, state);
-
- // update vector register
- m_chanB->set_vector(vector);
-
- // trigger interrupt
- m_int_state[priority] |= Z80_DAISY_INT;
- m_chanA->set_interrupt_pending();
-
- // check for interrupt
- check_interrupts();
-}
-
-
-//-------------------------------------------------
-// m1_r - interrupt acknowledge
-//-------------------------------------------------
-
-int z80dart_device::m1_r()
-{
- return z80daisy_irq_ack();
-}
-
-
-//-------------------------------------------------
-// cd_ba_r -
-//-------------------------------------------------
-
-uint8_t z80dart_device::cd_ba_r(offs_t offset)
-{
- int ba = BIT(offset, 0);
- int cd = BIT(offset, 1);
- z80dart_channel *channel = ba ? m_chanB : m_chanA;
-
- return cd ? channel->control_read() : channel->data_read();
-}
-
-
-//-------------------------------------------------
-// cd_ba_w -
-//-------------------------------------------------
-
-void z80dart_device::cd_ba_w(offs_t offset, uint8_t data)
-{
- int ba = BIT(offset, 0);
- int cd = BIT(offset, 1);
- z80dart_channel *channel = ba ? m_chanB : m_chanA;
-
- if (cd)
- channel->control_write(data);
- else
- channel->data_write(data);
-}
-
-
-//-------------------------------------------------
-// ba_cd_r -
-//-------------------------------------------------
-
-uint8_t z80dart_device::ba_cd_r(offs_t offset)
-{
- int ba = BIT(offset, 1);
- int cd = BIT(offset, 0);
- z80dart_channel *channel = ba ? m_chanB : m_chanA;
-
- return cd ? channel->control_read() : channel->data_read();
-}
-
-
-//-------------------------------------------------
-// ba_cd_w -
-//-------------------------------------------------
-
-void z80dart_device::ba_cd_w(offs_t offset, uint8_t data)
-{
- int ba = BIT(offset, 1);
- int cd = BIT(offset, 0);
- z80dart_channel *channel = ba ? m_chanB : m_chanA;
-
- if (cd)
- channel->control_write(data);
- else
- channel->data_write(data);
-}
-
-
-
-//**************************************************************************
-// DART CHANNEL
-//**************************************************************************
-
-//-------------------------------------------------
-// dart_channel - constructor
-//-------------------------------------------------
-
-z80dart_channel::z80dart_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, Z80DART_CHANNEL, tag, owner, clock)
- , device_serial_interface(mconfig, *this)
- , m_rx_error(0)
- , m_rx_clock(0)
- , m_rx_first(0)
- , m_rx_break(0)
- , m_rx_rr0_latch(0)
- , m_rxd(1)
- , m_ri(0)
- , m_cts(0)
- , m_dcd(0)
- , m_tx_data(0)
- , m_tx_clock(0)
- , m_dtr(0)
- , m_rts(0)
- , m_sync(0)
-{
- for (auto & elem : m_rr)
- elem = 0;
-
- for (auto & elem : m_wr)
- elem = 0;
-}
-
-
-//-------------------------------------------------
-// start - channel startup
-//-------------------------------------------------
-
-void z80dart_channel::device_start()
-{
- m_uart = downcast<z80dart_device *>(owner());
- m_index = m_uart->get_channel_index(this);
-
- // state saving
- save_item(NAME(m_rr));
- save_item(NAME(m_wr));
- // save_item(NAME(m_rx_data_fifo));
- // save_item(NAME(m_rx_error_fifo));
- save_item(NAME(m_rx_clock));
- save_item(NAME(m_rx_first));
- save_item(NAME(m_rx_break));
- save_item(NAME(m_rx_rr0_latch));
- save_item(NAME(m_ri));
- save_item(NAME(m_cts));
- save_item(NAME(m_dcd));
- save_item(NAME(m_tx_data));
- save_item(NAME(m_tx_clock));
- save_item(NAME(m_dtr));
- save_item(NAME(m_rts));
- save_item(NAME(m_sync));
-}
-
-
-//-------------------------------------------------
-// reset - reset channel status
-//-------------------------------------------------
-
-void z80dart_channel::device_reset()
-{
- receive_register_reset();
- transmit_register_reset();
-
- // disable receiver
- m_wr[3] &= ~WR3_RX_ENABLE;
-
- // disable transmitter
- m_wr[5] &= ~WR5_TX_ENABLE;
- m_rr[0] |= RR0_TX_BUFFER_EMPTY;
- m_rr[1] |= RR1_ALL_SENT;
-
- // reset external lines
- set_rts(1);
- set_dtr(1);
-
- // reset interrupts
- if (m_index == z80dart_device::CHANNEL_A)
- {
- m_uart->reset_interrupts();
- }
-}
-
-
-//-------------------------------------------------
-// tra_callback -
-//-------------------------------------------------
-
-void z80dart_channel::tra_callback()
-{
- if (!(m_wr[5] & WR5_TX_ENABLE))
- {
- // transmit mark
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_txda_cb(1);
- else
- m_uart->m_out_txdb_cb(1);
- }
- else if (m_wr[5] & WR5_SEND_BREAK)
- {
- // transmit break
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_txda_cb(0);
- else
- m_uart->m_out_txdb_cb(0);
- }
- else if (!is_transmit_register_empty())
- {
- // transmit data
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_txda_cb(transmit_register_get_data_bit());
- else
- m_uart->m_out_txdb_cb(transmit_register_get_data_bit());
- }
-}
-
-
-//-------------------------------------------------
-// tra_complete -
-//-------------------------------------------------
-
-void z80dart_channel::tra_complete()
-{
- if ((m_wr[5] & WR5_TX_ENABLE) && !(m_wr[5] & WR5_SEND_BREAK) && !(m_rr[0] & RR0_TX_BUFFER_EMPTY))
- {
- LOG("Z80DART \"%s\" Channel %c : Transmit Data Byte '%02x'\n", owner()->tag(), 'A' + m_index, m_tx_data);
-
- transmit_register_setup(m_tx_data);
-
- // empty transmit buffer
- m_rr[0] |= RR0_TX_BUFFER_EMPTY;
-
- if (m_wr[1] & WR1_TX_INT_ENABLE)
- m_uart->trigger_interrupt(m_index, INT_TRANSMIT);
- }
- else if (m_wr[5] & WR5_SEND_BREAK)
- {
- // transmit break
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_txda_cb(0);
- else
- m_uart->m_out_txdb_cb(0);
- }
- else
- {
- // transmit mark
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_txda_cb(1);
- else
- m_uart->m_out_txdb_cb(1);
- }
-
- // if transmit buffer is empty
- if (m_rr[0] & RR0_TX_BUFFER_EMPTY)
- {
- // then all characters have been sent
- m_rr[1] |= RR1_ALL_SENT;
-
- // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
- if (!m_rts)
- set_rts(1);
- }
-}
-
-
-//-------------------------------------------------
-// rcv_callback -
-//-------------------------------------------------
-
-void z80dart_channel::rcv_callback()
-{
- if (m_wr[3] & WR3_RX_ENABLE)
- {
- receive_register_update_bit(m_rxd);
- }
-}
-
-
-//-------------------------------------------------
-// rcv_complete -
-//-------------------------------------------------
-
-void z80dart_channel::rcv_complete()
-{
- receive_register_extract();
- receive_data(get_received_char());
-}
-
-
-//-------------------------------------------------
-// get_clock_mode - get clock divisor
-//-------------------------------------------------
-
-int z80dart_channel::get_clock_mode()
-{
- int clocks = 1;
-
- switch (m_wr[4] & WR4_CLOCK_RATE_MASK)
- {
- case WR4_CLOCK_RATE_X1: clocks = 1; break;
- case WR4_CLOCK_RATE_X16: clocks = 16; break;
- case WR4_CLOCK_RATE_X32: clocks = 32; break;
- case WR4_CLOCK_RATE_X64: clocks = 64; break;
- }
-
- return clocks;
-}
-
-
-//-------------------------------------------------
-// get_stop_bits - get number of stop bits
-//-------------------------------------------------
-
-device_serial_interface::stop_bits_t z80dart_channel::get_stop_bits()
-{
- switch (m_wr[4] & WR4_STOP_BITS_MASK)
- {
- case WR4_STOP_BITS_1: return STOP_BITS_1;
- case WR4_STOP_BITS_1_5: return STOP_BITS_1_5;
- case WR4_STOP_BITS_2: return STOP_BITS_2;
- }
-
- return STOP_BITS_0;
-}
-
-
-//-------------------------------------------------
-// get_rx_word_length - get receive word length
-//-------------------------------------------------
-
-int z80dart_channel::get_rx_word_length()
-{
- int bits = 5;
-
- switch (m_wr[3] & WR3_RX_WORD_LENGTH_MASK)
- {
- case WR3_RX_WORD_LENGTH_5: bits = 5; break;
- case WR3_RX_WORD_LENGTH_6: bits = 6; break;
- case WR3_RX_WORD_LENGTH_7: bits = 7; break;
- case WR3_RX_WORD_LENGTH_8: bits = 8; break;
- }
-
- return bits;
-}
-
-
-//-------------------------------------------------
-// get_tx_word_length - get transmit word length
-//-------------------------------------------------
-
-int z80dart_channel::get_tx_word_length()
-{
- int bits = 5;
-
- switch (m_wr[5] & WR5_TX_WORD_LENGTH_MASK)
- {
- case WR5_TX_WORD_LENGTH_5: bits = 5; break;
- case WR5_TX_WORD_LENGTH_6: bits = 6; break;
- case WR5_TX_WORD_LENGTH_7: bits = 7; break;
- case WR5_TX_WORD_LENGTH_8: bits = 8; break;
- }
-
- return bits;
-}
-
-
-//-------------------------------------------------
-// control_read - read control register
-//-------------------------------------------------
-
-uint8_t z80dart_channel::control_read()
-{
- uint8_t data = 0;
-
- int reg = m_wr[0] & WR0_REGISTER_MASK;
-
- if (reg != 0)
- {
- // mask out register index
- m_wr[0] &= ~WR0_REGISTER_MASK;
- }
-
- switch (reg)
- {
- case 0:
- case 1:
- data = m_rr[reg];
- break;
-
- case 2:
- // channel B only
- if (m_index == z80dart_device::CHANNEL_B)
- data = m_rr[reg];
- break;
- }
-
- //LOG("Z80DART \"%s\" Channel %c : Control Register Read '%02x'\n", owner()->tag(), 'A' + m_index, data);
-
- return data;
-}
-
-
-//-------------------------------------------------
-// control_write - write control register
-//-------------------------------------------------
-
-void z80dart_channel::control_write(uint8_t data)
-{
- int reg = m_wr[0] & WR0_REGISTER_MASK;
- uint8_t prev = m_wr[reg];
-
- LOG("Z80DART \"%s\" Channel %c : Control Register Write '%02x'\n", owner()->tag(), 'A' + m_index, data);
-
- // write data to selected register
- if (reg < 6)
- m_wr[reg] = data;
-
- if (reg != 0)
- {
- // mask out register index
- m_wr[0] &= ~WR0_REGISTER_MASK;
- }
-
- switch (reg)
- {
- case 0:
- switch (data & WR0_COMMAND_MASK)
- {
- case WR0_NULL:
- LOG("Z80DART \"%s\" Channel %c : Null\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR0_SEND_ABORT:
- LOG("Z80DART \"%s\" Channel %c : Send Abort\n", owner()->tag(), 'A' + m_index);
- logerror("Z80DART \"%s\" Channel %c : unsupported command: Send Abort\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR0_RESET_EXT_STATUS:
- // reset external/status interrupt
- m_rr[0] &= ~(RR0_DCD | RR0_RI | RR0_CTS | RR0_BREAK_ABORT);
-
- if (!m_dcd) m_rr[0] |= RR0_DCD;
- if (m_ri) m_rr[0] |= RR0_RI;
- if (!m_cts) m_rr[0] |= RR0_CTS;
-
- m_rx_rr0_latch = 0;
-
- LOG("Z80DART \"%s\" Channel %c : Reset External/Status Interrupt\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR0_CHANNEL_RESET:
- // channel reset
- LOG("Z80DART \"%s\" Channel %c : Channel Reset\n", owner()->tag(), 'A' + m_index);
- device_reset();
- break;
-
- case WR0_ENABLE_INT_NEXT_RX:
- // enable interrupt on next receive character
- LOG("Z80DART \"%s\" Channel %c : Enable Interrupt on Next Received Character\n", owner()->tag(), 'A' + m_index);
- m_rx_first = 1;
- break;
-
- case WR0_RESET_TX_INT:
- // reset transmitter interrupt pending
- LOG("Z80DART \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", owner()->tag(), 'A' + m_index);
- logerror("Z80DART \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR0_ERROR_RESET:
- // error reset
- LOG("Z80DART \"%s\" Channel %c : Error Reset\n", owner()->tag(), 'A' + m_index);
- m_rr[1] &= ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR);
- break;
-
- case WR0_RETURN_FROM_INT:
- // return from interrupt
- LOG("Z80DART \"%s\" Channel %c : Return from Interrupt\n", owner()->tag(), 'A' + m_index);
- m_uart->z80daisy_irq_reti();
- if((m_uart->m_variant == z80dart_device::TYPE_I8274) || (m_uart->m_variant == z80dart_device::TYPE_UPD7201))
- {
- if (m_uart->m_chanB->get_status_vector())
- {
- if((m_uart->m_chanA->m_wr[1] & 0x18) == z80dart_channel::WR2_MODE_8086_8088)
- m_uart->m_chanB->m_rr[2] = (m_uart->m_chanB->m_wr[2] & 0xf8) | 0x07;
- else
- m_uart->m_chanB->m_rr[2] = (m_uart->m_chanB->m_wr[2] & 0xe3) | 0x1c;
- }
- }
- break;
- }
- break;
-
- case 1:
- LOG("Z80DART \"%s\" Channel %c : External Interrupt Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR1_EXT_INT_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Transmit Interrupt Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR1_TX_INT_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Status Affects Vector %u\n", owner()->tag(), 'A' + m_index, (data & WR1_STATUS_VECTOR) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Wait/Ready Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR1_WRDY_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Wait/Ready Function %s\n", owner()->tag(), 'A' + m_index, (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait");
- LOG("Z80DART \"%s\" Channel %c : Wait/Ready on %s\n", owner()->tag(), 'A' + m_index, (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit");
-
- switch (data & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_DISABLE:
- LOG("Z80DART \"%s\" Channel %c : Receiver Interrupt Disabled\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR1_RX_INT_FIRST:
- LOG("Z80DART \"%s\" Channel %c : Receiver Interrupt on First Character\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR1_RX_INT_ALL_PARITY:
- LOG("Z80DART \"%s\" Channel %c : Receiver Interrupt on All Characters, Parity Affects Vector\n", owner()->tag(), 'A' + m_index);
- break;
-
- case WR1_RX_INT_ALL:
- LOG("Z80DART \"%s\" Channel %c : Receiver Interrupt on All Characters\n", owner()->tag(), 'A' + m_index);
- break;
- }
-
- m_uart->check_interrupts();
- break;
-
- case 2:
- // interrupt vector
- if (m_index == z80dart_device::CHANNEL_B)
- {
- if(get_status_vector())
- m_rr[2] = ( m_rr[2] & 0x0e ) | ( m_wr[2] & 0xF1);
- else
- m_rr[2] = m_wr[2];
- }
- m_uart->check_interrupts();
- LOG("Z80DART \"%s\" Channel %c : Interrupt Vector %02x\n", owner()->tag(), 'A' + m_index, data);
- break;
-
- case 3:
- LOG("Z80DART \"%s\" Channel %c : Receiver Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR3_RX_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Auto Enables %u\n", owner()->tag(), 'A' + m_index, (data & WR3_AUTO_ENABLES) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Receiver Bits/Character %u\n", owner()->tag(), 'A' + m_index, get_rx_word_length());
-
- if (data != prev)
- update_serial();
- break;
-
- case 4:
- LOG("Z80DART \"%s\" Channel %c : Parity Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR4_PARITY_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Parity %s\n", owner()->tag(), 'A' + m_index, (data & WR4_PARITY_EVEN) ? "Even" : "Odd");
- LOG("Z80DART \"%s\" Channel %c : Stop Bits %s\n", owner()->tag(), 'A' + m_index, stop_bits_tostring(get_stop_bits()));
- LOG("Z80DART \"%s\" Channel %c : Clock Mode %uX\n", owner()->tag(), 'A' + m_index, get_clock_mode());
-
- if (data != prev)
- update_serial();
- break;
-
- case 5:
- LOG("Z80DART \"%s\" Channel %c : Transmitter Enable %u\n", owner()->tag(), 'A' + m_index, (data & WR5_TX_ENABLE) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Transmitter Bits/Character %u\n", owner()->tag(), 'A' + m_index, get_tx_word_length());
- LOG("Z80DART \"%s\" Channel %c : Send Break %u\n", owner()->tag(), 'A' + m_index, (data & WR5_SEND_BREAK) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Request to Send %u\n", owner()->tag(), 'A' + m_index, (data & WR5_RTS) ? 1 : 0);
- LOG("Z80DART \"%s\" Channel %c : Data Terminal Ready %u\n", owner()->tag(), 'A' + m_index, (data & WR5_DTR) ? 1 : 0);
-
- // don't update if parameters haven't changed; in fact, don't update at all since these ones are currently unused
- if (0 && (data & WR5_TX_WORD_LENGTH_MASK) != (prev & WR5_TX_WORD_LENGTH_MASK))
- update_serial();
-
- if (data & WR5_RTS)
- {
- // when the RTS bit is set, the _RTS output goes low
- set_rts(0);
- m_rts = 1;
- }
- else
- {
- // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
- if (m_rr[1] & RR1_ALL_SENT)
- set_rts(1);
- m_rts = 0;
- }
-
- // data terminal ready output follows the state programmed into the DTR bit*/
- set_dtr((data & WR5_DTR) ? 0 : 1);
- break;
-
- case 6:
- LOG("Z80DART \"%s\" Channel %c : Transmit Sync %02x\n", owner()->tag(), 'A' + m_index, data);
- m_sync = (m_sync & 0xff00) | data;
- break;
-
- case 7:
- LOG("Z80DART \"%s\" Channel %c : Receive Sync %02x\n", owner()->tag(), 'A' + m_index, data);
- m_sync = (data << 8) | (m_sync & 0xff);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// data_read - read data register
-//-------------------------------------------------
-
-uint8_t z80dart_channel::data_read()
-{
- uint8_t data = 0;
-
- if (!m_rx_data_fifo.empty())
- {
- // load data from the FIFO
- data = m_rx_data_fifo.dequeue();
-
- // load error status from the FIFO
- m_rr[1] = (m_rr[1] & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo.dequeue();
-
- if (m_rx_data_fifo.empty())
- {
- // no more characters available in the FIFO
- m_rr[0] &= ~ RR0_RX_CHAR_AVAILABLE;
- }
- }
-
- LOG("Z80DART \"%s\" Channel %c : Data Register Read '%02x'\n", owner()->tag(), 'A' + m_index, data);
-
- return data;
-}
-
-
-//-------------------------------------------------
-// data_write - write data register
-//-------------------------------------------------
-
-void z80dart_channel::data_write(uint8_t data)
-{
- m_tx_data = data;
-
- if ((m_wr[5] & WR5_TX_ENABLE) && is_transmit_register_empty())
- {
- LOG("Z80DART \"%s\" Channel %c : Transmit Data Byte '%02x'\n", owner()->tag(), 'A' + m_index, m_tx_data);
-
- transmit_register_setup(m_tx_data);
-
- // empty transmit buffer
- m_rr[0] |= RR0_TX_BUFFER_EMPTY;
-
- if (m_wr[1] & WR1_TX_INT_ENABLE)
- m_uart->trigger_interrupt(m_index, INT_TRANSMIT);
- }
- else
- {
- m_rr[0] &= ~RR0_TX_BUFFER_EMPTY;
- }
-
- m_rr[1] &= ~RR1_ALL_SENT;
-
- LOG("Z80DART \"%s\" Channel %c : Data Register Write '%02x'\n", owner()->tag(), 'A' + m_index, data);
-}
-
-
-//-------------------------------------------------
-// receive_data - receive data word
-//-------------------------------------------------
-
-void z80dart_channel::receive_data(uint8_t data)
-{
- LOG("Z80DART \"%s\" Channel %c : Receive Data Byte '%02x'\n", owner()->tag(), 'A' + m_index, data);
-
- if (m_rx_data_fifo.full())
- {
- // receive overrun error detected
- m_rx_error |= RR1_RX_OVERRUN_ERROR;
-
- switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_FIRST:
- if (!m_rx_first)
- {
- m_uart->trigger_interrupt(m_index, INT_SPECIAL);
- }
- break;
-
- case WR1_RX_INT_ALL_PARITY:
- case WR1_RX_INT_ALL:
- m_uart->trigger_interrupt(m_index, INT_SPECIAL);
- break;
- }
- // overwrite last character/error with received character and error status into FIFO
- m_rx_data_fifo.poke(data);
- m_rx_error_fifo.poke(m_rx_error);
- }
- else
- {
- // store received character and error status into FIFO
- m_rx_data_fifo.enqueue(data);
- m_rx_error_fifo.enqueue(m_rx_error);
- }
-
- m_rr[0] |= RR0_RX_CHAR_AVAILABLE;
-
- // receive interrupt
- switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
- {
- case WR1_RX_INT_FIRST:
- if (m_rx_first)
- {
- m_uart->trigger_interrupt(m_index, INT_RECEIVE);
-
- m_rx_first = 0;
- }
- break;
-
- case WR1_RX_INT_ALL_PARITY:
- case WR1_RX_INT_ALL:
- m_uart->trigger_interrupt(m_index, INT_RECEIVE);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// cts_w - clear to send handler
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::cts_w )
-{
- LOG("Z80DART \"%s\" Channel %c : CTS %u\n", owner()->tag(), 'A' + m_index, state);
-
- if (m_cts != state)
- {
- // enable transmitter if in auto enables mode
- if (!state)
- if (m_wr[3] & WR3_AUTO_ENABLES)
- m_wr[5] |= WR5_TX_ENABLE;
-
- // set clear to send
- m_cts = state;
-
- if (!m_rx_rr0_latch)
- {
- if (!m_cts)
- m_rr[0] |= RR0_CTS;
- else
- m_rr[0] &= ~RR0_CTS;
-
- // trigger interrupt
- if (m_wr[1] & WR1_EXT_INT_ENABLE)
- {
- // trigger interrupt
- m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
-
- // latch read register 0
- m_rx_rr0_latch = 1;
- }
- }
- }
-}
-
-
-//-------------------------------------------------
-// dcd_w - data carrier detected handler
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::dcd_w )
-{
- LOG("Z80DART \"%s\" Channel %c : DCD %u\n", owner()->tag(), 'A' + m_index, state);
-
- if (m_dcd != state)
- {
- // enable receiver if in auto enables mode
- if (!state)
- if (m_wr[3] & WR3_AUTO_ENABLES)
- m_wr[3] |= WR3_RX_ENABLE;
-
- // set data carrier detect
- m_dcd = state;
-
- if (!m_rx_rr0_latch)
- {
- if (m_dcd)
- m_rr[0] |= RR0_DCD;
- else
- m_rr[0] &= ~RR0_DCD;
-
- if (m_wr[1] & WR1_EXT_INT_ENABLE)
- {
- // trigger interrupt
- m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
-
- // latch read register 0
- m_rx_rr0_latch = 1;
- }
- }
- }
-}
-
-
-//-------------------------------------------------
-// ri_w - ring indicator handler
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::ri_w )
-{
- LOG("Z80DART \"%s\" Channel %c : RI %u\n", owner()->tag(), 'A' + m_index, state);
-
- if (m_ri != state)
- {
- // set ring indicator state
- m_ri = state;
-
- if (!m_rx_rr0_latch)
- {
- if (m_ri)
- m_rr[0] |= RR0_RI;
- else
- m_rr[0] &= ~RR0_RI;
-
- if (m_wr[1] & WR1_EXT_INT_ENABLE)
- {
- // trigger interrupt
- m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
-
- // latch read register 0
- m_rx_rr0_latch = 1;
- }
- }
- }
-}
-
-
-//-------------------------------------------------
-// sync_w - sync handler
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::sync_w )
-{
- LOG("Z80DART \"%s\" Channel %c : SYNC %u\n", owner()->tag(), 'A' + m_index, state);
-}
-
-
-//-------------------------------------------------
-// rxc_w - receive clock
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::rxc_w )
-{
- //LOG("Z80DART \"%s\" Channel %c : Receiver Clock Pulse\n", owner()->tag(), m_index + 'A');
- int clocks = get_clock_mode();
- if (clocks == 1)
- rx_clock_w(state);
- else if(state)
- {
- rx_clock_w(m_rx_clock < clocks/2);
-
- m_rx_clock++;
- if (m_rx_clock == clocks)
- m_rx_clock = 0;
-
- }
-}
-
-
-//-------------------------------------------------
-// txc_w - transmit clock
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( z80dart_channel::txc_w )
-{
- //LOG("Z80DART \"%s\" Channel %c : Transmitter Clock Pulse\n", owner()->tag(), m_index + 'A');
- int clocks = get_clock_mode();
- if (clocks == 1)
- tx_clock_w(state);
- else if(state)
- {
- tx_clock_w(m_tx_clock < clocks/2);
-
- m_tx_clock++;
- if (m_tx_clock == clocks)
- m_tx_clock = 0;
-
- }
-}
-
-
-//-------------------------------------------------
-// update_serial -
-//-------------------------------------------------
-
-void z80dart_channel::update_serial()
-{
- int data_bit_count = get_rx_word_length();
- stop_bits_t stop_bits = get_stop_bits();
-
- parity_t parity;
- if (m_wr[4] & WR4_PARITY_ENABLE)
- {
- if (m_wr[4] & WR4_PARITY_EVEN)
- parity = PARITY_EVEN;
- else
- parity = PARITY_ODD;
- }
- else
- parity = PARITY_NONE;
-
- set_data_frame(1, data_bit_count, parity, stop_bits);
-
- int clocks = get_clock_mode();
-
- if (m_rxc > 0)
- {
- set_rcv_rate(m_rxc / clocks);
- }
-
- if (m_txc > 0)
- {
- set_tra_rate(m_txc / clocks);
- }
- receive_register_reset(); // if stop bits is changed from 0, receive register has to be reset (FIXME: doing this without checking is stupid)
-}
-
-
-//-------------------------------------------------
-// set_dtr -
-//-------------------------------------------------
-
-void z80dart_channel::set_dtr(int state)
-{
- m_dtr = state;
-
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_dtra_cb(m_dtr);
- else
- m_uart->m_out_dtrb_cb(m_dtr);
-}
-
-
-//-------------------------------------------------
-// set_rts -
-//-------------------------------------------------
-
-void z80dart_channel::set_rts(int state)
-{
- if (m_index == z80dart_device::CHANNEL_A)
- m_uart->m_out_rtsa_cb(state);
- else
- m_uart->m_out_rtsb_cb(state);
-}
-
-
-//-------------------------------------------------
-// write_rx -
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(z80dart_channel::write_rx)
-{
- m_rxd = state;
- //only use rx_w when self-clocked
- if(m_rxc)
- device_serial_interface::rx_w(state);
-}