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.
12 KiB
DUART datasheet verification — SCN2681 / MC68681
Subject: the two "datasheet-backed" MAME mc68681.cpp/.h edits (commit
9902722165fc) that make the VT1200 level-1 HOST PORT self-test progress, plus the
incidental FIFO-depth claim.
This verification is done against the datasheet, not against the code. The MAME
tree (/home/arti/code/k-space/mame0289) was reverted and re-modified by another
worker several times during this audit; a snapshot of the modified diff and of upstream
0.289 is kept under reference/duart-datasheet/.
Sources used
| File | What it is |
|---|---|
reference/duart-datasheet/SCN2681-transputer.pdf (+ .txt) |
Primary. Philips Semiconductors SCN2681 DUART product specification, dated 1995 May 1. The part actually fitted to the VT1200 is the Signetics/Philips SCN2681. |
reference/duart-datasheet/SCC2681-nxp.pdf (+ .txt) |
Philips SCC2681 datasheet, 2004 Apr 06 (same family, later rev) — corroboration. |
reference/duart-datasheet/SCN68681-xdevs.pdf (+ .txt) |
Signetics SCN68681 datasheet — corroboration. |
reference/duart-datasheet/MC68681UM-nxp.pdf (+ .txt) |
Motorola MC68HC681 User's Manual (MC68681 / MC2681 family) — the Motorola-flavoured text, for the cross-family comparison. |
reference/duart-datasheet/MC2681-motorola-retroweb.pdf, SCN2681-signetics-tcd.pdf |
Additional copies (scanned / image-only; kept for provenance). |
reference/duart-datasheet/mc68681-VT1200-worker-diff.patch |
Snapshot of the worker's uncommitted MAME diff. |
reference/duart-datasheet/mc68681-upstream-0.289-transmit.txt |
Pristine upstream (MAME 0.289 clone commit f34f02505e32) transmit/RX code. |
Page numbers below are the printed page numbers in the Philips SCN2681 document
(each page footer reads 1995 May 1 <n>).
Summary
| # | Claim | Verdict |
|---|---|---|
| 1 | TxRDY must be asserted in tra_complete() (at the THR→TSR transfer / character boundary), because "Data is transferred … when it is idle or has completed transmission of the previous character. The TxRDY conditions are then asserted again", so upstream's tra_callback() assertion ("not until the end of start bit time") was wrong. |
REFUTED |
| 2 | The overrun error is latched on the start bit of the overrunning character, not when that character completes; MAME's rx_fifo_push() latch is a whole character late. |
CONFIRMED (one caveat) |
| 3 | MAME's receive FIFO is faithful: 3-deep, a 4th character held, overrun on the 5th. | CONFIRMED |
Claim 1 — TxRDY assertion point — REFUTED
The cited sentence is real. SCN2681, printed page 7, section "TRANSMITTER OPERATION" (also page 3-2 of the MC68HC681 User's Manual):
"The SCN2681 indicates to the CPU that it is ready to accept a character by setting the TxRDY bit in the status register. … When a character is loaded into the Transmit Holding Register (THR), the above conditions are negated. 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 means one full character time of buffering is provided."
But that sentence does not establish when, and the datasheet does establish it — in the opposite direction. SCN2681, printed page 22, section "The CTS, RTS, CTS Enable Tx signals" → "Transmitter Disable Note":
"TxRDY sets at the end of the "start bit" time. It is during the start bit that the data in the transmit holding register is transferred to the transmit shift register."
The same sentence appears verbatim in the 2004 Philips SCC2681 (p. 22) and the Signetics SCN68681. It is the datasheet's only statement of TxRDY timing relative to the start bit, and it agrees with the code the worker removed.
Upstream was right. The removed block was:
// 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();
}
m_bits_transmitted is reset to 0 when a character is loaded into the transmit shift
register (write_TX idle case, and tra_complete transfer case). tra_callback() is
called once per transmit-clock edge and the first call emits the start bit
(device_serial_interface::transmit_register_get_data_bit() returns the frame MSB
first). So the condition ++m_bits_transmitted > 1 first fires on the second edge —
i.e. at the end of the start-bit interval. Upstream's comment is a near-verbatim
restatement of the datasheet sentence on page 22, and upstream implemented it
correctly.
What the citation actually describes is the THR→TSR transfer — the same event
upstream's tra_complete() buffered branch already handled ("Data is transferred …
when … it has completed transmission of the previous character"). It says nothing about
deferring the assertion to full character completion, which is what the worker's change
does (it removes the page-22 assertion and relies on tra_complete() alone). Asserting
TxRDY at tra_complete() moves it ~1 character earlier than the datasheet's
"end of the start bit time".
Cross-family note (as requested): the Motorola MC68HC681 User's Manual does not contain the "end of the start bit time" sentence — it only says (§4.3.9.6, SRA[2]) "Transmitter ready is set when the character is transferred to the transmit shift register." On this point the Motorola text is the weaker/less specific of the two. The VT1200 part is the SCN2681 (Philips/Signetics), so page 22 governs, and it refutes the claim.
Assessment: the quoted sentence exists and is accurately transcribed, but it does not justify the change; the datasheet's explicit TxRDY-timing sentence supports the behaviour that was removed.
Claim 2 — Overrun latch point — CONFIRMED (with one caveat)
The cited wording is real and explicit. SCN2681, printed page 8, section "Receiver FIFO":
"The RHR consists of a First-In-First-Out (FIFO) stack with a capacity of three characters. … If the FIFO is full when a new character is received, that character is held in the receive shift register until a FIFO position is available. If an additional character is received while this state exits[sic], the contents of the FIFO are not affected; the character previously in the shift register is lost and the overrun error status bit (SR[4] will be set-upon receipt of the start bit of the new (overrunning) character)."
Corroborated by the SRA[4] definition, SCN2681 printed page 14:
"SRA[4] – Channel A Overrun Error — This bit, when set indicates that one or more characters in the received data stream have been lost. It is set upon receipt of a new character when the FIFO is full and a character is already in the receive shift register waiting for an empty FIFO position."
and by the MC68HC681 User's Manual (§3.2, p. 3-3/3-4):
"… the character previously in the shift register is lost and the overrun-error status bit will be set upon receipt of the start bit of the new overrunning character."
So the datasheet does say "start bit", not "when the character has been received".
MAME's original rx_fifo_push() latches STATUS_OVERRUN_ERROR only when the overrunning
character has been fully received (it is called from rcv_complete()), i.e. ~one
character late. The worker's direction of correction is datasheet-backed.
Caveat 1 (datasheet is internally in tension). SCN2681 page 8 also says:
"The parity error, framing error, overrun error and received break state (if any) are strobed into the SR at the received character boundary, before the RxRDY status bit is set."
Taken alone this reads like completion timing. It is a general statement about all four error/break flags; the overrun-specific sentence ("upon receipt of the start bit") is the more specific and repeated one (it appears in all four datasheets), and SRA[4] repeats "upon receipt of a new character". So the start-bit reading is the better-supported one — but the datasheet is not perfectly self-consistent on this point, and a reader could be forgiven for the completion reading.
Caveat 2 (which "start bit"?). The datasheet defines a start bit as received only
after it is validated: "the state of the RxD pin is sampled each 16X clock for 7 1/2
clocks … If RxD is still Low, a valid start bit is assumed" (p. 8). "Upon receipt of the
start bit" therefore means ~½ bit time after the falling edge, not at the falling
edge itself. The worker's duart_channel::rx_w() latches on the falling edge
(state == 0), i.e. about half a bit earlier than the datasheet. For the overrun
condition this is inconsequential, but it is not a literal implementation of the text.
Assessment: confirmed. The datasheet explicitly latches overrun at the start bit of the overrunning character; MAME's completion-time latch was late. (Minor caveats above.)
Claim 3 — FIFO depth — CONFIRMED
Datasheet. SCN2681, printed page 8, section "Receiver FIFO":
"The RHR consists of a First-In-First-Out (FIFO) stack with a capacity of three characters."
and, immediately after (same page):
"If the FIFO is full when a new character is received, that character is held in the receive shift register until a FIFO position is available. If an additional character is received while this state exits[sic] … the overrun error status bit (SR[4]) will be set …"
So: three characters in the FIFO, a fourth held in the receive shift register, and overrun on the fifth — exactly "3-deep, 4th held, overrun on 5th". The MC68HC681 User's Manual agrees ("consists of three receive holding registers. … data flowing from the receiver to the CPU is quadruply buffered", p. 3-3).
MAME. MC68681_RX_FIFO_SIZE == 3, FIFO array rx_fifo[MC68681_RX_FIFO_SIZE + 1]
(4 slots). rx_fifo_num is incremented only while <= 3 (so it reaches 4 on the 4th
character) and rx_fifo_push() sets STATUS_OVERRUN_ERROR when it is called with
rx_fifo_num == MC68681_RX_FIFO_SIZE + 1 == 4 — i.e. when the 5th character is
pushed. STATUS_FIFO_FULL is set when rx_fifo_num == 3. This matches the datasheet's
threshold: 3 in the FIFO, 4th accepted, overrun on the 5th.
Assessment: confirmed. The +1 array slot and the SIZE+1 overrun guard model the
datasheet's "FIFO of three + one held in the shift register" correctly. This part of the
worker's reasoning is not the source of the test failure.
Incidental findings
- Local loopback clock. SCN2681, printed page 12 (MR2A[7:6] = 10, local loopback mode): "2. The transmit clock is used for the receiver." The report's §5.4 note (MAME clocks the loopback receiver from the independent receive clock) is directionally correct against the datasheet. Not one of the three claims under review.
- "Receipt of a start bit" vs falling edge applies to Claim 2 (above).
- The datasheet's own inconsistency ("strobed … at the received character boundary" vs "set upon receipt of the start bit") is the only place any of these three points fails to be unambiguous; on Claim 1 there is no ambiguity — page 22 is explicit.
Bottom line
Only one of the three cited justifications holds up as written. Claim 2 and Claim 3
are accurately quoted and correctly applied. Claim 1 is the misleading one: its
quotation is genuine, but the datasheet contains a more specific sentence — "TxRDY sets
at the end of the 'start bit' time" (SCN2681 p. 22) — that says the opposite of what the
edit assumes, and which the removed upstream code implemented. Removing the
tra_callback() assertion is not datasheet-backed.