diff --git a/src/devices/machine/mc68681.cpp b/src/devices/machine/mc68681.cpp index 70d3cfd0bb30..077cc0a0d38e 100644 --- a/src/devices/machine/mc68681.cpp +++ b/src/devices/machine/mc68681.cpp @@ -1326,6 +1326,7 @@ duart_channel::duart_channel(const machine_config &mconfig, const char *tag, dev , SR(0) , rx_enabled(0) , rx_fifo_num(0) + , m_rx_line(true) , m_tx_data_in_buffer(false) , m_tx_break(false) , m_bits_transmitted(255) @@ -1357,6 +1358,26 @@ void duart_channel::device_start() save_item(NAME(m_tx_break)); save_item(NAME(m_bits_transmitted)); save_item(NAME(m_tx_enabled)); + save_item(NAME(m_rx_line)); +} + +// VT1200 NOTE (local change, not upstream): the datasheet latches the overrun +// error "upon receipt of the start bit of the new (overrunning) character", +// i.e. while the FIFO is full and the previous character is still held in the +// receive shift register. MAME's rx_fifo_push() latches it only when that +// character is fully received, a whole character late. Watching the RxD line +// here reproduces the earlier latch time. Revert: delete this override, delete +// the m_rx_line member, and restore the device_serial_interface::rx_w calls in +// mc68681.h's rx_a_w/rx_b_w/rx_c_w/rx_d_w. +void duart_channel::rx_w(int state) +{ + if (state == 0 && m_rx_line && (rx_fifo_num == MC68681_RX_FIFO_SIZE + 1)) + { + SR |= STATUS_OVERRUN_ERROR; + update_interrupts(); + } + m_rx_line = (state != 0); + device_serial_interface::rx_w(state); } void duart_channel::device_reset() @@ -1451,6 +1472,18 @@ void duart_channel::tra_complete() else { SR |= STATUS_TRANSMITTER_EMPTY; + // VT1200 NOTE (local change, not upstream): also assert TxRDY here. The + // VT1200 level-1 host-port test runs an interrupt-driven loopback: the + // DUART ISR writes the pattern byte on TxRDYA and, per transmit, reads + // SRA and expects the RX FIFO to have filled in step (FFULL before the + // 5th byte, OVR after it). Asserting TxRDY mid-character (see the + // removed block in tra_callback below) made the ISR one byte ahead of + // the receiver, so the snapshots were FFULL/OVR one index too late and + // the test failed. Asserting TxRDY when the shift register empties + // (the THR->TSR transfer point) makes the ISR pace one byte per + // character. Revert: delete the STATUS_TRANSMITTER_READY term below + // and restore the removed block in tra_callback. + SR |= STATUS_TRANSMITTER_READY; update_interrupts(); } } @@ -1485,12 +1518,21 @@ void duart_channel::tra_callback() 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 && m_tx_enabled) - { - SR |= STATUS_TRANSMITTER_READY; - update_interrupts(); - } + // VT1200 NOTE (local change, not upstream): the upstream code asserted + // TxRDY here ("not until the end of start bit time") when no byte was + // buffered. The datasheet instead asserts TxRDY at the THR->TSR transfer + // ("Data is transferred from the holding register to transmit shift + // register when it is idle or has completed transmission of the previous + // character. The TxRDY conditions are then asserted again"), which is the + // character boundary for a buffered byte -- not mid-character. Asserting + // on the start bit made the VT1200 loopback test's ISR run one byte ahead + // of the receiver. Revert: remove the increment below and restore + // if (m_bits_transmitted++ > 0 && !m_tx_data_in_buffer && m_tx_enabled) + // { + // SR |= STATUS_TRANSMITTER_READY; + // update_interrupts(); + // } + m_bits_transmitted++; } void duart_channel::update_interrupts() diff --git a/src/devices/machine/mc68681.h b/src/devices/machine/mc68681.h index d5476e822c2f..c1e09db44d94 100644 --- a/src/devices/machine/mc68681.h +++ b/src/devices/machine/mc68681.h @@ -31,6 +31,11 @@ public: void write_chan_reg(int reg, uint8_t data); void update_interrupts(); + // VT1200 NOTE (local change, not upstream): saw the RxD line so the overrun + // error can be latched on the start bit of the overrunning character (the + // datasheet's timing), rather than at its completion in rx_fifo_push(). + void rx_w(int state); + void rx_fifo_push(uint8_t data, uint8_t errors); uint8_t read_rx_fifo(); @@ -67,6 +72,7 @@ private: int rx_fifo_read_ptr; int rx_fifo_write_ptr; int rx_fifo_num; + bool m_rx_line; // VT1200 NOTE (local): previous RxD line state int m_ch; @@ -108,8 +114,8 @@ public: virtual uint8_t read(offs_t offset); virtual void write(offs_t offset, uint8_t data); - void rx_a_w(int state) { m_chanA->device_serial_interface::rx_w((uint8_t)state); } - void rx_b_w(int state) { m_chanB->device_serial_interface::rx_w((uint8_t)state); } + void rx_a_w(int state) { m_chanA->rx_w((uint8_t)state); } + void rx_b_w(int state) { m_chanB->rx_w((uint8_t)state); } auto irq_cb() { return write_irq.bind(); } auto a_tx_cb() { return write_a_tx.bind(); }