Files
vt1200/reference/mc68681-datasheet-verification.md
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

12 KiB
Raw Blame History

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.