From 3166f52c3fa865449879e08f8c62b832babb2ac0 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 17 Nov 2017 19:00:23 +1100 Subject: [PATCH] restore most of 5ad509e4b2d3c8a989c8342ae60900d169abeba0, use arays for callbacks (nw) --- src/devices/machine/z80sio.cpp | 101 +++++++++++++++++++++------------ src/devices/machine/z80sio.h | 72 ++++++++++------------- 2 files changed, 93 insertions(+), 80 deletions(-) diff --git a/src/devices/machine/z80sio.cpp b/src/devices/machine/z80sio.cpp index 388e147d900..056b001e404 100644 --- a/src/devices/machine/z80sio.cpp +++ b/src/devices/machine/z80sio.cpp @@ -154,9 +154,9 @@ enum : uint8_t WR1_RX_INT_FIRST = 0x08, WR1_RX_INT_ALL_PARITY = 0x10, WR1_RX_INT_ALL = 0x18, - WR1_WRDY_ON_RX_TX = 0x20, // not supported - WR1_WRDY_FUNCTION = 0x40, // not supported - WR1_WRDY_ENABLE = 0x80 // not supported + WR1_WRDY_ON_RX_TX = 0x20, + WR1_WRDY_FUNCTION = 0x40, // WAIT not supported + WR1_WRDY_ENABLE = 0x80 }; enum : uint8_t @@ -259,17 +259,24 @@ MACHINE_CONFIG_END inline void z80sio_channel::out_txd_cb(int state) { - ((m_index == z80sio_device::CHANNEL_A) ? m_uart->m_out_txda_cb : m_uart->m_out_txdb_cb)(state); + m_uart->m_out_txd_cb[m_index](state); } inline void z80sio_channel::out_rts_cb(int state) { - ((m_index == z80sio_device::CHANNEL_A) ? m_uart->m_out_rtsa_cb : m_uart->m_out_rtsb_cb)(state); + m_uart->m_out_rts_cb[m_index](state); } inline void z80sio_channel::out_dtr_cb(int state) { - ((m_index == z80sio_device::CHANNEL_A) ? m_uart->m_out_dtra_cb : m_uart->m_out_dtrb_cb)(state); + m_uart->m_out_dtr_cb[m_index](state); +} + +inline void z80sio_channel::set_ready(bool ready) +{ + // WAIT mode not supported yet + if (m_wr1 & WR1_WRDY_FUNCTION) + m_uart->m_out_wrdy_cb[m_index](ready ? 0 : 1); } inline bool z80sio_channel::transmit_allowed() const @@ -343,21 +350,14 @@ z80sio_device::z80sio_device(const machine_config &mconfig, device_type type, co device_z80daisy_interface(mconfig, *this), m_chanA(*this, CHANA_TAG), m_chanB(*this, CHANB_TAG), - 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_txd_cb{ { *this }, { *this } }, + m_out_dtr_cb{ { *this }, { *this } }, + m_out_rts_cb{ { *this }, { *this } }, + m_out_wrdy_cb{ { *this }, { *this } }, + m_out_sync_cb{ { *this }, { *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_out_rxdrq_cb{ { *this }, { *this } }, + m_out_txdrq_cb{ { *this }, { *this } }, m_cputag(nullptr) { for (auto & elem : m_int_state) @@ -392,21 +392,21 @@ void z80sio_device::device_resolve_objects() LOG("%s\n", FUNCNAME); // 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_txd_cb[CHANNEL_A].resolve_safe(); + m_out_dtr_cb[CHANNEL_A].resolve_safe(); + m_out_rts_cb[CHANNEL_A].resolve_safe(); + m_out_wrdy_cb[CHANNEL_A].resolve_safe(); + m_out_sync_cb[CHANNEL_A].resolve_safe(); + m_out_txd_cb[CHANNEL_B].resolve_safe(); + m_out_dtr_cb[CHANNEL_B].resolve_safe(); + m_out_rts_cb[CHANNEL_B].resolve_safe(); + m_out_wrdy_cb[CHANNEL_B].resolve_safe(); + m_out_sync_cb[CHANNEL_B].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(); + m_out_rxdrq_cb[CHANNEL_A].resolve_safe(); + m_out_txdrq_cb[CHANNEL_A].resolve_safe(); + m_out_rxdrq_cb[CHANNEL_B].resolve_safe(); + m_out_txdrq_cb[CHANNEL_B].resolve_safe(); } //------------------------------------------------- @@ -1016,6 +1016,8 @@ void z80sio_channel::device_reset() m_rr1 |= RR1_ALL_SENT; m_tx_flags = 0U; + // TODO: what happens to WAIT/READY? + // reset external lines out_rts_cb(m_rts = 1); out_dtr_cb(m_dtr = 1); @@ -1042,6 +1044,8 @@ void z80sio_channel::transmit_enable() { LOGTX("Channel %c synchronous transmit enabled - load sync pattern\n", 'A' + m_index); tx_setup_idle(); + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(true); } else if (!(m_rr0 & RR0_TX_BUFFER_EMPTY)) { @@ -1077,6 +1081,7 @@ void z80sio_channel::sync_tx_sr_empty() LOGTX("%s() Channel %c Transmitter Disabled m_wr5:%02x\n", FUNCNAME, 'A' + m_index, m_wr5); // transmit disabled, set flag if nothing pending + m_tx_flags &= ~TX_FLAG_SPECIAL; if (m_rr0 & RR0_TX_BUFFER_EMPTY) m_rr1 |= RR1_ALL_SENT; } @@ -1087,6 +1092,8 @@ void z80sio_channel::sync_tx_sr_empty() // empty transmit buffer m_rr0 |= RR0_TX_BUFFER_EMPTY; + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(true); if (m_wr1 & WR1_TX_INT_ENABLE) m_uart->trigger_interrupt(m_index, INT_TRANSMIT); } @@ -1097,6 +1104,8 @@ void z80sio_channel::sync_tx_sr_empty() tx_setup_idle(); // if this is the first sync pattern, generate an interrupt indicating that the next frame can be sent + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(true); if (first_idle && (m_wr1 & WR1_TX_INT_ENABLE)) m_uart->trigger_interrupt(m_index, INT_TRANSMIT); m_rr1 |= RR1_ALL_SENT; @@ -1129,6 +1138,8 @@ void z80sio_channel::async_tx_setup() // empty transmit buffer m_rr0 |= RR0_TX_BUFFER_EMPTY; + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(true); if (m_wr1 & WR1_TX_INT_ENABLE) m_uart->trigger_interrupt(m_index, INT_TRANSMIT); } @@ -1423,6 +1434,8 @@ void z80sio_channel::do_sioreg_wr0(uint8_t data) tx_setup(0xff, 8, 0, true, true); m_rr0 |= RR0_TX_BUFFER_EMPTY; m_rr1 &= ~RR1_ALL_SENT; + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(false); break; case WR0_RESET_EXT_STATUS: reset_ext_status(); @@ -1499,6 +1512,13 @@ void z80sio_channel::do_sioreg_wr1(uint8_t data) LOG("Z80SIO \"%s\" Channel %c : Receiver Interrupt on All Characters\n", owner()->tag(), 'A' + m_index); break; } + + if (!(data & WR1_WRDY_ENABLE)) + set_ready(false); + else if (data & WR1_WRDY_ON_RX_TX) + set_ready(bool(m_rr0 & RR0_RX_CHAR_AVAILABLE)); + else + set_ready((m_rr0 & RR0_TX_BUFFER_EMPTY) && !(m_tx_flags & TX_FLAG_SPECIAL)); } void z80sio_channel::do_sioreg_wr2(uint8_t data) @@ -1614,6 +1634,8 @@ void z80sio_channel::data_write(uint8_t data) m_tx_data = data; m_rr0 &= ~RR0_TX_BUFFER_EMPTY; m_rr1 &= ~RR1_ALL_SENT; + if ((m_wr1 & WR1_WRDY_ENABLE) && !(m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(false); // handle automatic RTS bool const async((m_wr4 & WR4_STOP_BITS_MASK) != WR4_STOP_BITS_SYNC); @@ -1670,6 +1692,8 @@ void z80sio_channel::advance_rx_fifo() { // no more characters available in the FIFO m_rr0 &= ~RR0_RX_CHAR_AVAILABLE; + if ((m_wr1 & WR1_WRDY_ENABLE) && (m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(false); m_uart->clear_interrupt(m_index, INT_RECEIVE); } } @@ -1719,6 +1743,8 @@ void z80sio_channel::receive_data() } m_rr0 |= RR0_RX_CHAR_AVAILABLE; + if ((m_wr1 & WR1_WRDY_ENABLE) && (m_wr1 & WR1_WRDY_ON_RX_TX)) + set_ready(true); if (!m_rx_fifo_depth) m_rr1 |= uint8_t(rx_error); @@ -1849,15 +1875,16 @@ WRITE_LINE_MEMBER( z80sio_channel::rxc_w ) // sample a data/parity/stop bit if (!m_rxd) m_rx_sr &= ~uint16_t(1U << (m_rx_bit - 1)); - LOGBIT("%s() \"%s \"Channel %c Received Data Bit %d\n", FUNCNAME, owner()->tag(), 'A' + m_index, m_rxd); + bool const stop_reached((get_rx_word_length() + ((m_wr4 & WR4_PARITY_ENABLE) ? 1 : 0) + 1) == m_rx_bit); + LOGBIT("%s() Channel %c Received %s Bit %d\n", FUNCNAME, 'A' + m_index, stop_reached ? "Stop" : "Data", m_rxd); - if ((get_rx_word_length() + ((m_wr4 & WR4_PARITY_ENABLE) ? 1 : 0) + 1) == m_rx_bit) + if (stop_reached) { // this is the stop bit - framing error adds a half bit period m_rx_count = m_rxd ? (clocks / 2) : clocks; m_rx_bit = 0; - LOGRCV("%s() \"%s \"Channel %c Received Data %02x\n", FUNCNAME, owner()->tag(), 'A' + m_index, m_rx_sr & 0xff); + LOGRCV("%s() Channel %c Received Data %02x&\n", FUNCNAME, 'A' + m_index, m_rx_sr & 0xff); receive_data(); } else diff --git a/src/devices/machine/z80sio.h b/src/devices/machine/z80sio.h index a048ac41780..bff002ccc12 100644 --- a/src/devices/machine/z80sio.h +++ b/src/devices/machine/z80sio.h @@ -75,47 +75,47 @@ // Port A callbacks #define MCFG_Z80SIO_OUT_TXDA_CB(_devcb) \ - devcb = &z80sio_device::set_out_txda_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_txd_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_DTRA_CB(_devcb) \ - devcb = &z80sio_device::set_out_dtra_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_dtr_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_RTSA_CB(_devcb) \ - devcb = &z80sio_device::set_out_rtsa_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_rts_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_WRDYA_CB(_devcb) \ - devcb = &z80sio_device::set_out_wrdya_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_wrdy_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_SYNCA_CB(_devcb) \ - devcb = &z80sio_device::set_out_synca_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_sync_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_RXDRQA_CB(_devcb) \ - devcb = &z80sio_device::set_out_rxdrqa_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_rxdrq_callback<0>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_TXDRQA_CB(_devcb) \ - devcb = &z80sio_device::set_out_txdrqa_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_txdrq_callback<0>(*device, DEVCB_##_devcb); // Port B callbacks #define MCFG_Z80SIO_OUT_TXDB_CB(_devcb) \ - devcb = &z80sio_device::set_out_txdb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_txd_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_DTRB_CB(_devcb) \ - devcb = &z80sio_device::set_out_dtrb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_dtr_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_RTSB_CB(_devcb) \ - devcb = &z80sio_device::set_out_rtsb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_rts_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_WRDYB_CB(_devcb) \ - devcb = &z80sio_device::set_out_wrdyb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_wrdy_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_SYNCB_CB(_devcb) \ - devcb = &z80sio_device::set_out_syncb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_sync_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_RXDRQB_CB(_devcb) \ - devcb = &z80sio_device::set_out_rxdrqb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_rxdrq_callback<1>(*device, DEVCB_##_devcb); #define MCFG_Z80SIO_OUT_TXDRQB_CB(_devcb) \ - devcb = &z80sio_device::set_out_txdrqb_callback(*device, DEVCB_##_devcb); + devcb = &z80sio_device::set_out_txdrq_callback<1>(*device, DEVCB_##_devcb); //************************************************************************** @@ -297,6 +297,7 @@ private: void out_txd_cb(int state); void out_rts_cb(int state); void out_dtr_cb(int state); + void set_ready(bool ready); bool transmit_allowed() const; void receive_data(); @@ -337,21 +338,14 @@ public: // construction/destruction z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - template static devcb_base &set_out_txda_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txda_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_dtra_callback(device_t &device, Object &&cb) { return downcast(device).m_out_dtra_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_rtsa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rtsa_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_wrdya_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wrdya_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_synca_callback(device_t &device, Object &&cb) { return downcast(device).m_out_synca_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_txdb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txdb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_dtrb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_dtrb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_rtsb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rtsb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_wrdyb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wrdyb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_syncb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_syncb_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_out_txd_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txd_cb[N].set_callback(std::forward(cb)); } + template static devcb_base &set_out_dtr_callback(device_t &device, Object &&cb) { return downcast(device).m_out_dtr_cb[N].set_callback(std::forward(cb)); } + template static devcb_base &set_out_rts_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rts_cb[N].set_callback(std::forward(cb)); } + template static devcb_base &set_out_wrdy_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wrdy_cb[N].set_callback(std::forward(cb)); } + template static devcb_base &set_out_sync_callback(device_t &device, Object &&cb) { return downcast(device).m_out_sync_cb[N].set_callback(std::forward(cb)); } template static devcb_base &set_out_int_callback(device_t &device, Object &&cb) { return downcast(device).m_out_int_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_rxdrqa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rxdrqa_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_txdrqa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txdrqa_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_rxdrqb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rxdrqb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_txdrqb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txdrqb_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_out_rxdrq_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rxdrq_cb[N].set_callback(std::forward(cb)); } + template static devcb_base &set_out_txdrq_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txdrq_cb[N].set_callback(std::forward(cb)); } static void static_set_cputag(device_t &device, const char *tag) { @@ -426,23 +420,15 @@ protected: required_device m_chanB; // internal state - devcb_write_line m_out_txda_cb; - devcb_write_line m_out_dtra_cb; - devcb_write_line m_out_rtsa_cb; - devcb_write_line m_out_wrdya_cb; - devcb_write_line m_out_synca_cb; - - devcb_write_line m_out_txdb_cb; - devcb_write_line m_out_dtrb_cb; - devcb_write_line m_out_rtsb_cb; - devcb_write_line m_out_wrdyb_cb; - devcb_write_line m_out_syncb_cb; + devcb_write_line m_out_txd_cb[2]; + devcb_write_line m_out_dtr_cb[2]; + devcb_write_line m_out_rts_cb[2]; + devcb_write_line m_out_wrdy_cb[2]; + devcb_write_line m_out_sync_cb[2]; devcb_write_line m_out_int_cb; - devcb_write_line m_out_rxdrqa_cb; - devcb_write_line m_out_txdrqa_cb; - devcb_write_line m_out_rxdrqb_cb; - devcb_write_line m_out_txdrqb_cb; + devcb_write_line m_out_rxdrq_cb[2]; + devcb_write_line m_out_txdrq_cb[2]; int m_int_state[8]; // interrupt state int m_int_source[8]; // interrupt source