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.
210 lines
12 KiB
Markdown
210 lines
12 KiB
Markdown
# 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:
|
||
|
||
```c++
|
||
// 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.
|