mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
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.
122 lines
4.9 KiB
Diff
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(); }
|