Files
vt1200/reference/duart-datasheet/mc68681-VT1200-worker-diff.patch
T
SDD 031d30da67 reference: DUART datasheet verification of the two mc68681 edits (claim 1 refuted)
Download the SCN2681 (Philips 1995), SCC2681, SCN68681 and MC68HC681 UM
datasheets into reference/duart-datasheet/ with pdftotext extractions, and
audit each claimed justification against them:

  Claim 1 (TxRDY asserted in tra_complete, not tra_callback): REFUTED.
    The quoted p.7 sentence is real, but SCN2681 p.22 says explicitly
    'TxRDY sets at the end of the start bit time' -- which is exactly the
    removed upstream behaviour.  Upstream was right.

  Claim 2 (overrun latched on the start bit, not completion): CONFIRMED.
    'the overrun error status bit (SR[4]) will be set upon receipt of the
    start bit of the new (overrunning) character' (p.8, also SRA[4] p.14).
    Caveats: p.8 also says errors are 'strobed ... at the received
    character boundary' (internal tension); and a valid start bit is
    validated ~half a bit after the falling edge, not at it.

  Claim 3 (3-deep FIFO, 4th held, overrun on 5th; MAME faithful): CONFIRMED.
    'capacity of three characters' + 4th held in the shift register (p.8);
    MAME's SIZE+1 guard overruns exactly on the 5th.

Also snapshot the worker's uncommitted MAME diff and upstream 0.289 code.
2026-10-16 12:13:07 +03:00

122 lines
4.9 KiB
Diff

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(); }