diff options
Diffstat (limited to 'src/devices/cpu/z180/z180asci.cpp')
-rw-r--r-- | src/devices/cpu/z180/z180asci.cpp | 694 |
1 files changed, 694 insertions, 0 deletions
diff --git a/src/devices/cpu/z180/z180asci.cpp b/src/devices/cpu/z180/z180asci.cpp new file mode 100644 index 00000000000..298afe55932 --- /dev/null +++ b/src/devices/cpu/z180/z180asci.cpp @@ -0,0 +1,694 @@ +// license:BSD-3-Clause +// copyright-holders:Miodrag Milanovic +/********************************************************************* + + z180asci.cpp + +*********************************************************************/ + +#include "emu.h" +#include "z180.h" + +//#define VERBOSE 1 + +#include "logmacro.h" + +/* 00 ASCI control register A ch 0 */ +static constexpr u8 Z180_CNTLA_MPE = 0x80; +static constexpr u8 Z180_CNTLA_RE = 0x40; +static constexpr u8 Z180_CNTLA_TE = 0x20; +static constexpr u8 Z180_CNTLA_RTS0 = 0x10; +static constexpr u8 Z180_CNTLA_MPBR_EFR = 0x08; +static constexpr u8 Z180_CNTLA_MODE = 0x07; +static constexpr u8 Z180_CNTLA_MODE_DATA = 0x04; +static constexpr u8 Z180_CNTLA_MODE_PARITY = 0x02; +static constexpr u8 Z180_CNTLA_MODE_STOPB = 0x01; + +/* 01 ASCI control register A ch 1 */ +static constexpr u8 Z180_CNTLA1_CKA1D = 0x10; + +/* 02/03 ASCI control register B ch 0 */ +static constexpr u8 Z180_CNTLB_MPBT = 0x80; +static constexpr u8 Z180_CNTLB_MP = 0x40; +static constexpr u8 Z180_CNTLB_CTS_PS = 0x20; +static constexpr u8 Z180_CNTLB_PEO = 0x10; +static constexpr u8 Z180_CNTLB_DR = 0x08; +static constexpr u8 Z180_CNTLB_SS = 0x07; + +/* 04 ASCI status register 0 (all bits read-only except RIE and TIE) */ +static constexpr u8 Z180_STAT_RDRF = 0x80; +static constexpr u8 Z180_STAT_OVRN = 0x40; +static constexpr u8 Z180_STAT_PE = 0x20; +static constexpr u8 Z180_STAT_FE = 0x10; +static constexpr u8 Z180_STAT_RIE = 0x08; +static constexpr u8 Z180_STAT_DCD0 = 0x04; +static constexpr u8 Z180_STAT_TDRE = 0x02; +static constexpr u8 Z180_STAT_TIE = 0x01; + +/* 05 ASCI status register 1 (all bits read-only except RIE, CTS1E and TIE) */ +static constexpr u8 Z180_STAT1_CTS1E = 0x04; + +/* 12/13 (Z8S180/Z8L180) ASCI extension control register 0 (break detect is read-only) */ +static constexpr u8 Z180_ASEXT_DCD0 = 0x40; +static constexpr u8 Z180_ASEXT_CTS0 = 0x20; +static constexpr u8 Z180_ASEXT_X1_BIT_CLK0 = 0x10; +static constexpr u8 Z180_ASEXT_BRG0_MODE = 0x08; +static constexpr u8 Z180_ASEXT_BRK_EN = 0x04; +static constexpr u8 Z180_ASEXT_BRK_DET = 0x02; +static constexpr u8 Z180_ASEXT_BRK_SEND = 0x01; + +static constexpr u8 Z180_ASEXT0_MASK = 0x7f; +static constexpr u8 Z180_ASEXT1_MASK = 0x1f; + + +//************************************************************************** +// z180asci_channel_base +//************************************************************************** + +z180asci_channel_base::z180asci_channel_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const int id, const bool ext) + : device_t(mconfig, type, tag, owner, clock) + , m_rcv_clock(nullptr) + , m_tra_clock(nullptr) + , m_bit_rate(attotime::never) + , m_sample_rate(attotime::never) + , m_txa_handler(*this) + , m_rts_handler(*this) + , m_cka_handler(*this) + , m_cts(0) + , m_dcd(0) + , m_irq(0) + , m_rts(0) + , m_divisor(0) + , m_id(id) + , m_ext(ext) +{ +} + + +void z180asci_channel_base::device_start() +{ + save_item(NAME(m_asci_cntla)); + save_item(NAME(m_asci_cntlb)); + save_item(NAME(m_asci_stat)); + save_item(NAME(m_asci_tdr)); + save_item(NAME(m_asci_rdr)); + if (m_ext) + { + save_item(NAME(m_asci_ext)); + save_item(NAME(m_asci_tc.w)); + } + save_item(NAME(m_tsr)); + save_item(NAME(m_rsr)); + save_item(NAME(m_data_fifo)); + save_item(NAME(m_error_fifo)); + save_item(NAME(m_fifo_wr)); + save_item(NAME(m_fifo_rd)); + + save_item(NAME(m_cts)); + save_item(NAME(m_dcd)); + save_item(NAME(m_irq)); + save_item(NAME(m_txa)); + save_item(NAME(m_rxa)); + save_item(NAME(m_rts)); + + save_item(NAME(m_divisor)); + + save_item(NAME(m_clock_state)); + + save_item(NAME(m_tx_counter)); + save_item(NAME(m_tx_state)); + + save_item(NAME(m_rx_state)); + save_item(NAME(m_rx_bits)); + save_item(NAME(m_rx_counter)); + save_item(NAME(m_rx_count_to)); + save_item(NAME(m_rx_total_bits)); + save_item(NAME(m_rx_enabled)); + + save_item(NAME(m_bit_rate)); + save_item(NAME(m_sample_rate)); + + + m_rcv_clock = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z180asci_channel_base::rcv_clock), this)); + m_tra_clock = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z180asci_channel_base::tra_clock), this)); + +} + +void z180asci_channel_base::device_reset() +{ + m_asci_ext = 0; + m_asci_tc.w = 0; + + m_fifo_wr = 0; + m_fifo_rd = 0; + + output_txa(1); + output_rts(1); + + m_tsr = 0; + m_rxa = 1; + m_clock_state = 0; + m_tx_state = STATE_WAIT; + m_rx_state = STATE_START; + m_rx_bits = 0; + m_rx_enabled = true; + + m_tx_counter = 0; + m_rx_counter = 0; + m_rx_count_to = 1; +} + +void z180asci_channel_base::device_clock_changed() +{ + uint32_t brg_divisor; + // Divide ratio + m_divisor = (m_asci_ext & Z180_ASEXT_X1_BIT_CLK0) ? 1 : ((m_asci_cntlb & Z180_CNTLB_DR) ? 64 : 16); + + if ((m_asci_cntlb & Z180_CNTLB_SS) == Z180_CNTLB_SS) + { + // External clock + brg_divisor = 0; + } + else + { + if (m_asci_ext & Z180_ASEXT_BRG0_MODE) + { + // Extended boud rate generator mode + brg_divisor = m_asci_tc.w + 2; + } + else + { + // Regular bitrate generator mode + brg_divisor = 1 << (m_asci_cntlb & Z180_CNTLB_SS); + brg_divisor *= ((m_asci_cntlb & Z180_CNTLB_CTS_PS) ? 30 : 10); // Prescale + } + } + + if (brg_divisor) + { + LOG("Z180 ASCI%d set bitrate %d\n", m_id, uint32_t(clock() / brg_divisor / m_divisor)); + m_bit_rate = attotime::from_hz(clock() / brg_divisor / m_divisor); + m_sample_rate = attotime::from_hz(clock() / brg_divisor); + } + else + { + LOG("Z180 ASCI%d set bitrate 0, using external\n", m_id); + m_bit_rate = attotime::never; + m_sample_rate = attotime::never; + } + + m_tra_clock->adjust(attotime::never); + m_rx_state = STATE_START; + m_rx_count_to = 1; + if(!m_sample_rate.is_never()) + m_rcv_clock->adjust(m_sample_rate, 0, m_sample_rate); +} + +uint8_t z180asci_channel_base::cntla_r() +{ + LOG("Z180 CNTLA%d rd $%02x\n", m_id, m_asci_cntla); + return m_asci_cntla; +} + +uint8_t z180asci_channel_base::cntlb_r() +{ + uint8_t data = (m_asci_cntlb & 0xdf) | (m_cts << 5); + LOG("Z180 CNTLB%d rd $%02x\n", m_id, data); + return data; +} + +uint8_t z180asci_channel_base::stat_r() +{ + LOG("Z180 STAT%d rd $%02x\n", m_id, m_asci_stat); + return m_asci_stat; +} + +uint8_t z180asci_channel_base::tdr_r() +{ + LOG("Z180 TDR%d rd $%02x\n", m_id, m_asci_tdr); + return m_asci_tdr; +} + +uint8_t z180asci_channel_base::rdr_r() +{ + LOG("Z180 RDR%d rd $%02x\n", m_id, m_asci_rdr); + if (!machine().side_effects_disabled()) + { + if (m_fifo_rd != m_fifo_wr) + { + m_asci_rdr = m_data_fifo[m_fifo_rd]; + m_asci_stat &= ~(Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE); + m_asci_stat |= m_error_fifo[m_fifo_rd]; + if (m_asci_stat & (Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE)) + m_irq = 1; + m_fifo_rd = (m_fifo_rd + 1) & 3; + if (m_fifo_rd == m_fifo_wr) // empty + m_asci_stat &= ~Z180_STAT_RDRF; + } + } + return m_asci_rdr; +} + +uint8_t z180asci_channel_base::asext_r() +{ + LOG("Z180 ASEXT%d rd $%02x\n", m_id, m_asci_ext); + return m_asci_ext; +} + +uint8_t z180asci_channel_base::astcl_r() +{ + LOG("Z180 ASTC%dL rd $%02x ($%04x)\n", m_id, m_asci_tc.b.l, m_asci_tc.w); + return m_asci_tc.b.l; +} + +uint8_t z180asci_channel_base::astch_r() +{ + LOG("Z180 ASTC%dH rd $%02x ($%04x)\n", m_id, m_asci_tc.b.h, m_asci_tc.w); + return m_asci_tc.b.h; +} + +void z180asci_channel_base::update_total_bits() +{ + m_rx_total_bits = (m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7; + m_rx_total_bits += (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 2 : 1; + m_rx_total_bits += (m_asci_cntlb & Z180_CNTLB_MP) ? 1 : ((m_asci_cntla & Z180_CNTLA_MODE_PARITY) ? 1 : 0); +} + +void z180asci_channel_base::cntla_w(uint8_t data) +{ + LOG("Z180 CNTLA%d wr $%02x\n", m_id, data); + m_asci_cntla = data & ~(Z180_CNTLA_MPBR_EFR | Z180_CNTLA_RTS0); + output_rts(BIT(data,4)); // Z180_CNTLA_RTS0 + if (data & Z180_CNTLA_MPBR_EFR) // Error Flag Reset + { + m_asci_stat &= ~(Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE); + m_asci_ext &= ~(Z180_ASEXT_BRK_DET); + } + update_total_bits(); +} + +void z180asci_channel_base::cntlb_w(uint8_t data) +{ + LOG("Z180 CNTLB%d wr $%02x\n", m_id, data); + m_asci_cntlb = data; + device_clock_changed(); + update_total_bits(); +} + +void z180asci_channel_base::tdr_w(uint8_t data) +{ + LOG("Z180 TDR%d wr $%02x\n", m_id, data); + m_asci_tdr = data; + m_asci_stat &= ~Z180_STAT_TDRE; + + if (!m_bit_rate.is_never()) + m_tra_clock->adjust(m_bit_rate, 0, m_bit_rate); +} + +void z180asci_channel_base::rdr_w(uint8_t data) +{ + LOG("Z180 RDR%d wr $%02x\n", m_id, data); + if (!(m_asci_stat & Z180_STAT_RDRF)) + set_fifo_data(data, 0); +} + +void z180asci_channel_base::asext_w(uint8_t data) +{ + if (m_asci_ext & Z180_ASEXT_BRK_EN) + m_tx_state = (m_asci_ext & Z180_ASEXT_BRK_SEND) ? STATE_BREAK : STATE_WAIT; + device_clock_changed(); +} + +void z180asci_channel_base::astcl_w(uint8_t data) +{ + LOG("Z180 ASTC%dL wr $%02x\n", m_id, data); + m_asci_tc.b.l = data; + device_clock_changed(); +} + +void z180asci_channel_base::astch_w(uint8_t data) +{ + LOG("Z180 ASTC%dH wr $%02x\n", m_id, data); + m_asci_tc.b.h = data; + device_clock_changed(); +} + +void z180asci_channel_base::cts_wr(int state) +{ + if (m_id) + { + // For channel 1, CTS can be disabled + if ((m_asci_stat & Z180_STAT1_CTS1E) == 0) return; + } + else + { + // For channel 0, high resets TDRE + if (m_ext && state && (m_asci_ext & Z180_ASEXT_CTS0) == 0) + m_asci_stat |= Z180_STAT_TDRE; + } + m_cts = state; +} + +void z180asci_channel_base::dcd_wr(int state) +{ + if (m_id) + return; + + // In extended mode, DCD autoenables RX if configured + if (m_ext && (m_asci_ext & Z180_ASEXT_DCD0) == 0) + { + m_rx_enabled = state ? false : true; + if (state) + m_asci_ext &= ~(Z180_ASEXT_BRK_DET); + } + + m_dcd = state; + if (m_dcd) + m_irq = 1; +} + +void z180asci_channel_base::rxa_wr(int state) +{ + m_rxa = state; +} + +void z180asci_channel_base::cka_wr(int state) +{ + // For channel 1, CKA can be disabled + if (m_id && (m_asci_cntla & Z180_CNTLA1_CKA1D)) return; + + if(state != m_clock_state) + { + m_clock_state = state; + if(!state) + { + m_tx_counter++; + if (m_tx_counter != m_divisor) return; + m_tx_counter = 0; + if (m_asci_cntla & Z180_CNTLA_TE) + transmit_edge(); + } + else + { + m_rx_counter++; + if (m_rx_counter != m_rx_count_to) return; + m_rx_counter = 0; + if (m_rx_enabled && (m_asci_cntla & Z180_CNTLA_RE)) + receive_edge(); + } + } +} + +void z180asci_channel_base::prepare_tsr() +{ + int bits = (m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7; + + m_tsr = (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 3 : 1; // stop bit(s) + + if ((m_asci_cntlb & Z180_CNTLB_MP) || (m_asci_cntla & Z180_CNTLA_MODE_PARITY)) + { + m_tsr <<= 1; + if (m_asci_cntlb & Z180_CNTLB_MP) + { + m_tsr |= (m_asci_cntlb & Z180_CNTLB_MPBT) ? 1 : 0; + } + else + { + uint8_t parity = 0; + for (int i = 0; i < bits; i++) + parity ^= BIT(m_asci_tdr, i); + if (m_asci_cntlb & Z180_CNTLB_PEO) parity ^= 1; // odd parity + m_tsr |= parity; + } + } + m_tsr <<= bits; + m_tsr |= m_asci_tdr; + m_tsr <<= 1; // start bit +} + +void z180asci_channel_base::transmit_edge() +{ + if (m_asci_cntla & Z180_CNTLA_TE) + { + switch (m_tx_state) + { + case STATE_DATA: + output_txa(BIT(m_tsr, 0)); + m_tsr >>= 1; + if (m_tsr == 0) + { + m_asci_stat |= Z180_STAT_TDRE; + if (m_asci_stat & Z180_STAT_TIE) + { + m_irq = 1; + } + m_tx_state = STATE_WAIT; + m_tra_clock->adjust(attotime::never); + } + break; + case STATE_WAIT: + if ((m_asci_stat & Z180_STAT_TDRE) == 0) + { + prepare_tsr(); + m_tx_state = STATE_DATA; + } + break; + case STATE_BREAK: + output_txa(0); + break; + } + } +} + +void z180asci_channel_base::update_received() +{ + uint8_t rx_error = 0; + int data_bits = (m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7; + if (m_rsr == 0) // Break detect + { + m_asci_ext |= Z180_ASEXT_BRK_DET; + } + if (m_rxa == 0) + rx_error |= Z180_STAT_FE; + + if (m_asci_cntlb & Z180_CNTLB_MP) + { + m_asci_cntla |= ((m_rsr >> data_bits) & 1) ? Z180_CNTLA_MPBR_EFR : 0; + } + else if (m_asci_cntla & Z180_CNTLA_MODE_PARITY) + { + uint8_t parity = 0; + for (int i = 0; i < data_bits; i++) + parity ^= BIT(m_rsr, i); + if (m_asci_cntlb & Z180_CNTLB_PEO) parity ^= 1; // odd parity + if (((m_rsr >> data_bits) & 1) != parity) + rx_error |= Z180_STAT_PE; + } + // Skip only if MPE mode active and MPB is 0 + if (!((m_asci_cntla & Z180_CNTLA_MPE) && ((m_asci_cntla & Z180_CNTLA_MPBR_EFR) == 0))) + { + LOG("%s: %X received%s%s\n", machine().time().to_string(), m_rsr, (rx_error & Z180_STAT_FE) ? " (framing error)" : "", (rx_error & Z180_STAT_PE) ? " (bad parity)" : ""); + set_fifo_data(m_rsr, rx_error); + } +} + +void z180asci_channel_base::receive_edge() +{ + if (!m_rx_enabled) return; + + if (m_asci_cntla & Z180_CNTLA_RE) + { + switch (m_rx_state) + { + case STATE_START: + if(m_rxa == 0) + { + m_rx_state = STATE_DATA; + m_rx_bits = 0; + m_rsr = 0; + if(!(m_bit_rate.is_never())) + m_rcv_clock->adjust((m_divisor == 1) ? m_bit_rate : (m_bit_rate * 3) / 2, 0, m_bit_rate); + else + m_rx_count_to = (m_divisor == 1) ? m_divisor : (m_divisor * 3) / 2; + } + break; + case STATE_DATA: + m_rsr |= m_rxa << m_rx_bits; + m_rx_bits++; + m_rx_count_to = m_divisor; + if (m_rx_bits == m_rx_total_bits) + { + update_received(); + m_rx_state = STATE_START; + if(!m_sample_rate.is_never()) + m_rcv_clock->adjust(m_sample_rate, 0, m_sample_rate); + else + m_rx_count_to = 1; + } + break; + } + } +} + +void z180asci_channel_base::set_fifo_data(uint8_t data, uint8_t error) +{ + m_data_fifo[m_fifo_wr] = data; + m_error_fifo[m_fifo_wr] = error; + if (((m_fifo_wr + 1) & 3) == m_fifo_rd) // overrun + { + m_error_fifo[m_fifo_wr] |= Z180_STAT_OVRN; + } + else + { + m_error_fifo[m_fifo_wr] &= Z180_STAT_OVRN; + m_fifo_wr = (m_fifo_wr + 1) & 3; + } + m_asci_stat |= Z180_STAT_RDRF; + if (m_asci_stat & Z180_STAT_RIE) + { + m_irq = 1; + } +} + +void z180asci_channel_base::output_txa(int txa) +{ + if (m_txa != txa) + { + m_txa = txa; + m_txa_handler(m_txa); + } +} + +void z180asci_channel_base::output_rts(int rts) +{ + if (m_rts != rts) + { + m_rts = rts; + m_rts_handler(m_rts); + } +} + +//************************************************************************** +// z180asci_channel_0 +//************************************************************************** + +z180asci_channel_0::z180asci_channel_0(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext) + : z180asci_channel_base(mconfig, type, tag, owner, clock, 0, ext) +{ +} + +z180asci_channel_0::z180asci_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z180asci_channel_0(mconfig, Z180ASCI_CHANNEL_0, tag, owner, clock, false) +{ +} + +void z180asci_channel_0::device_reset() +{ + z180asci_channel_base::device_reset(); + cntla_w((m_asci_cntla & Z180_CNTLA_MPBR_EFR) | Z180_CNTLA_RTS0); + cntlb_w((m_asci_cntlb & (Z180_CNTLB_MPBT | Z180_CNTLB_CTS_PS)) | 0x07); + m_asci_stat = (m_asci_stat & Z180_STAT_DCD0) | Z180_STAT_TDRE; +} + +void z180asci_channel_0::state_add(device_state_interface &parent) +{ + parent.state_add(Z180_CNTLA0, "CNTLA0", m_asci_cntla); + parent.state_add(Z180_CNTLB0, "CNTLB0", m_asci_cntlb); + parent.state_add(Z180_STAT0, "STAT0", m_asci_stat); + parent.state_add(Z180_TDR0, "TDR0", m_asci_tdr); + parent.state_add(Z180_RDR0, "RDR0", m_asci_rdr); + if (m_ext) + { + parent.state_add(Z180_ASEXT0, "ASEXT0", m_asci_ext).mask(Z180_ASEXT0_MASK); + parent.state_add(Z180_ASTC0, "ASTC0", m_asci_tc.w); + } +} + +void z180asci_channel_0::stat_w(uint8_t data) +{ + LOG("Z180 STAT0 wr $%02x ($%02x)\n", data, data & (Z180_STAT_RIE | Z180_STAT_TIE)); + m_asci_stat = (m_asci_stat & ~(Z180_STAT_RIE | Z180_STAT_TIE)) | (data & (Z180_STAT_RIE | Z180_STAT_TIE)); +} + +void z180asci_channel_0::asext_w(uint8_t data) +{ + LOG("Z180 ASEXT0 wr $%02x ($%02x)\n", data, data & Z180_ASEXT0_MASK & ~Z180_ASEXT_BRK_DET); + m_asci_ext = (m_asci_ext & Z180_ASEXT_BRK_DET) | (data & Z180_ASEXT0_MASK & ~Z180_ASEXT_BRK_DET); + z180asci_channel_base::asext_w(data); +} + +//************************************************************************** +// z180asci_channel_1 +//************************************************************************** + +z180asci_channel_1::z180asci_channel_1(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext) + : z180asci_channel_base(mconfig, type, tag, owner, clock, 1, ext) +{ +} + +z180asci_channel_1::z180asci_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z180asci_channel_1(mconfig, Z180ASCI_CHANNEL_1, tag, owner, clock, false) +{ +} +void z180asci_channel_1::device_reset() +{ + z180asci_channel_base::device_reset(); + cntla_w((m_asci_cntla & Z180_CNTLA_MPBR_EFR) | Z180_CNTLA1_CKA1D); + cntlb_w((m_asci_cntlb & Z180_CNTLB_MPBT) | 0x07); + m_asci_stat = Z180_STAT_TDRE; +} + +void z180asci_channel_1::state_add(device_state_interface &parent) +{ + parent.state_add(Z180_CNTLA1, "CNTLA1", m_asci_cntla); + parent.state_add(Z180_CNTLB1, "CNTLB1", m_asci_cntlb); + parent.state_add(Z180_STAT1, "STAT1", m_asci_stat); + parent.state_add(Z180_TDR1, "TDR1", m_asci_tdr); + parent.state_add(Z180_RDR1, "RDR1", m_asci_rdr); + if (m_ext) + { + parent.state_add(Z180_ASEXT1, "ASEXT1", m_asci_ext).mask(Z180_ASEXT1_MASK); + parent.state_add(Z180_ASTC1, "ASTC1", m_asci_tc.w); + } +} + +void z180asci_channel_1::stat_w(uint8_t data) +{ + LOG("Z180 STAT1 wr $%02x ($%02x)\n", data, data & (Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE)); + m_asci_stat = (m_asci_stat & ~(Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE)) | (data & (Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE)); +} + +void z180asci_channel_1::asext_w(uint8_t data) +{ + LOG("Z180 ASEXT1 wr $%02x ($%02x)\n", data, data & Z180_ASEXT1_MASK & ~Z180_ASEXT_BRK_DET); + m_asci_ext = (m_asci_ext & Z180_ASEXT_BRK_DET) | (data & Z180_ASEXT1_MASK & ~Z180_ASEXT_BRK_DET); + z180asci_channel_base::asext_w(data); +} + +//************************************************************************** +// z180asci_ext_channel_0 +//************************************************************************** + +z180asci_ext_channel_0::z180asci_ext_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z180asci_channel_0(mconfig, Z180ASCI_EXT_CHANNEL_0, tag, owner, clock, true) +{ +} + +//************************************************************************** +// z180asci_channel_1 +//************************************************************************** + +z180asci_ext_channel_1::z180asci_ext_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z180asci_channel_1(mconfig, Z180ASCI_EXT_CHANNEL_1, tag, owner, clock, true) +{ +} + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(Z180ASCI_CHANNEL_0, z180asci_channel_0, "z180asci_channel_0", "Z180 ASCI Channel 0") +DEFINE_DEVICE_TYPE(Z180ASCI_CHANNEL_1, z180asci_channel_1, "z180asci_channel_1", "Z180 ASCI Channel 1") + +DEFINE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_0, z180asci_ext_channel_0, "z180asci_ext_channel_0", "Z180 ASCI Extended Channel 0") +DEFINE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_1, z180asci_ext_channel_1, "z180asci_ext_channel_1", "Z180 ASCI Extended Channel 1") |