forked from arti/vt1200
docs: establish causally what raises HOST PORT - 15; resolve the sub-test polarity; rule out the loopback-clock deviation as the cause
Call site (not a register snapshot): 3FA84FB0 calla L3FA6E4B0; 3FA84FE0 stores a8; 3FA85000 move a8,a8 / 3FA85010 jreq; the nonzero path ends at 3FA85360-3FA853A0 with a11 = 0x400 returned. Live breakpoint confirms code=0x400 enters the HOST PORT handler 3FDE9D70. So the quantity to zero is L3FA6E4B0's return value (all five descriptor fields zero). Polarity resolved: L3FA71BC0/L3FA753D0 return their 32-bit flag word, which is 0 iff all their checks pass, so L3FA6E4B0's bits are failure bits. My earlier "L3FA753D0 returns 0x408 while its checks pass" was a misread -- the same 32-bit word also carries the setf-4/setf-2 fields at a13(0xc4/c8/ca/cc). The checks are therefore the right quantity. Loopback-clock deviation (SCN2681 p.12 item 2): real but NOT the cause. CSRA=0x88 gives TX==RX==2400 baud, so the clock source changes only the sampling phase, not the bit count or the completion time; and the received bytes are already correct, so MAME samples the TX bit centres. Not changed (would be banking a green). Measured residual: a ~1-bit write->receive offset (completion at W+1.07 char vs a 1.00-char write interval), sourced from the ~1 bit between a THRA write and the first transmitted bit; forcing it to zero corrupted the sampling phase, so the half-bit TX offset is load-bearing. Model vs datasheet items 3/4/5: matches (loopback fills the FIFO with the receiver disabled, which is what CRA=5 then CRA=0xA relies on). Regression holds.
This commit is contained in:
1 parent
70e2486d57
commit
03e6a88b22
2 files changed
+110
No files matched your search
@@ -731,3 +731,90 @@ independently before it is written.
|
||||
* Console: `'LEVEL1/2 TESTING ** '` then `'LEVEL1/2 ERROR -> HOST PORT - 15 '` — **still
|
||||
present**; no next gate.
|
||||
* Regression (no `VT1200_*`): `PC=3FDCE400 samples=199` — **holds**.
|
||||
|
||||
---
|
||||
|
||||
# WHAT MAKES THE CALLER RAISE 0x400 — resolved empirically
|
||||
|
||||
The owner's gating worry (if the caller does not actually turn a nonzero `L3FA6E4B0`
|
||||
return into `0x400`, then fixing the sub-tests' checks cannot clear `HOST PORT - 15`)
|
||||
is resolved. Breakpoints at the call site and at the handler, one run
|
||||
(`harness/mame/hp_disp.lua`):
|
||||
|
||||
```
|
||||
DISPATCH-READ code=0000FFFF <- 'LEVEL1/2 TESTING **'
|
||||
CALL-L3FA6E4B0 <- call site 3FA84FB0
|
||||
AFTER-CALL a8=00000006 <- call site 3FA84FE0 stores a8
|
||||
CALLER-ERR-RET a8=00000006 a11=00000400 <- error path sets a11=0x400, returns it
|
||||
DISPATCH-READ code=00000400
|
||||
HOSTPORT-HANDLER code=00000400 <- handler 3FDE9D70 prints HOST PORT - 15
|
||||
```
|
||||
|
||||
So the chain is confirmed **at the call site**, not from a register snapshot:
|
||||
|
||||
* `3FA84FB0 calla L3FA6E4B0`; `3FA84FE0 move a8, *a13(0x160)` (the return);
|
||||
`3FA85000 move a8,a8 ; 3FA85010 jreq L3FA853D0` — **any nonzero takes the error path**;
|
||||
that path ends at `3FA85360 movi 0x400,a11 ; 3FA85380 *a7(0x40)=a11 ; 3FA853A0 a8=a11`.
|
||||
* `0x400` **is** the HOST PORT dispatch code (measured live at `3FDE9D70`). My earlier
|
||||
static reading of the dispatcher's `subi` chain suggested `0x3F8`; dis34's `subi`
|
||||
rendering is misleading here and the live value is authoritative.
|
||||
|
||||
**The quantity to zero is `L3FA6E4B0`'s return value**: it must be 0, i.e. *all five*
|
||||
descriptor fields must be 0.
|
||||
|
||||
## Polarity — resolved, and my earlier caveat was wrong
|
||||
|
||||
`L3FA71BC0` returns `*a13(0xc0)` (its 32-bit flag word) and `L3FA753D0` returns the same
|
||||
word (`3FA76550`) or `a9`, which is set to that word at `3FA76440` and is untouched by the
|
||||
success loop — so on success both return **0**. Therefore `L3FA6E4B0`'s bits are
|
||||
**failure** bits, and "nonzero" *does* mean "this sub-test failed its checks".
|
||||
|
||||
The earlier "`L3FA753D0` returns `0x408` while all its checks pass" was a **misread**: the
|
||||
32-bit flag word is not the four loop flags alone — `3FA76480`–`3FA76520` also write a
|
||||
4-bit field at `a13(0xc4)` and 2-bit fields at `a13(0xc8/ca/cc)`, which are inside the
|
||||
same 32-bit read. So `0x408` is a genuine failure, not a false positive. This also
|
||||
removes the concern that the checks are the wrong quantity: they are the right one.
|
||||
|
||||
## Is the local-loopback clock deviation the cause? No.
|
||||
|
||||
Mechanism, stated explicitly (the owner's requirement): `CSRA = 0x88` selects the same
|
||||
`calc_baud` value for TX and RX (the `rx` argument is unused in `duart_base_device`), so
|
||||
the two clocks are the **same rate** (2400 baud). Clocking the loopback receiver from the
|
||||
transmit clock therefore changes only the **sampling phase/edges**, not the rate — and it
|
||||
does **not** change how many bit-times the receiver takes (6.5) nor when it finishes.
|
||||
|
||||
Measured, it is not even observable: the received bytes are **correct**
|
||||
(`0x0A,0x1F,0x0A` = the pattern masked by 0x1F), so MAME already samples the TX bit
|
||||
centres; and the completion is `sync + 6.5` bits either way. **Verdict: a real deviation
|
||||
(SCN2681 p.12 item 2) but NOT the cause of the residual**, and it cannot move the symptom
|
||||
— so I did **not** change it rather than bank a green.
|
||||
|
||||
The measured residual is a **~1-bit write->receive offset**: `RX completion = W + 1.07
|
||||
char` while the write interval is `1.00 char`, so the received byte misses the next
|
||||
snapshot by 0.5 bit. Its source is the **~1 bit between a THRA write and the first
|
||||
transmitted bit** (`sync = W + 2605`, bit = 2604) — i.e. the transmit clock's first edge
|
||||
is at `2*m_tra_rate`, not `m_tra_rate`. I tried forcing it to `m_tra_rate` and to zero;
|
||||
the first did nothing and the second **corrupted the received bytes** (sampling moved to
|
||||
the bit boundaries), so the half-bit TX offset is load-bearing for the sampling phase.
|
||||
Not banked; recorded as the open item.
|
||||
|
||||
## The datasheet items checked against our model
|
||||
|
||||
* item 3 (TxDA held High) and item 4 (RxDA ignored): modelled — `tra_callback()` does not
|
||||
drive the TX pin in loopback and feeds the bit to `rx_w` instead; the external RxD input
|
||||
is unused in this mode.
|
||||
* item 5 (transmitter must be enabled, receiver need not be): **matches** —
|
||||
`rcv_complete()` pushes when `rx_enabled || loopback`, so the FIFO keeps filling with
|
||||
the receiver disabled, which is what the firmware's `CRA=0x05` then `CRA=0x0A`
|
||||
(bit1 = disable Rx, bit3 = disable Tx) sequence relies on. `write_CR(0x0A)` also
|
||||
disables the transmitter, and MAME lets the in-flight character finish (the tra timer is
|
||||
already running), so the 5-byte burst completes.
|
||||
* One minor deviation, not biting here: `write_CR`'s bit1 handler clears `RxRDY`, whereas
|
||||
the datasheet says a receiver *disable* preserves the FIFO and its status. `read_rx_fifo`
|
||||
re-derives `RxRDY`, and the test's SRA check looks only at the high nibble (`OVR`), so it
|
||||
does not affect this test.
|
||||
|
||||
## Acceptance / regression (current tree: edit 1 reverted, edit 2 kept)
|
||||
|
||||
* Console: `HOST PORT - 15` — **still present**; no next gate.
|
||||
* Regression: `PC=3FDCE400 samples=199` — **holds**.
|
||||
@@ -0,0 +1,23 @@
|
||||
-- hp_disp.lua -- what code value actually reaches the HOST PORT handler?
|
||||
-- Dispatcher reads the status code from bit 0x16F0 (CODE22_REPORT). HOST PORT
|
||||
-- handler = 3FDE9D70. Also log the host-port caller's 0x400 return site.
|
||||
local machine = manager.machine
|
||||
local cpu = machine.devices[':maincpu']
|
||||
local dbg = machine.debugger
|
||||
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
|
||||
local function bp(addr, body)
|
||||
dbg:command('bpset ' .. addr .. ',,{ ' .. body .. ' ; g }')
|
||||
end
|
||||
bp("3fde9d70", 'printf "HOSTPORT-HANDLER code=%08X\\n", d@16F0')
|
||||
bp("3fa84fb0", 'printf "CALL-L3FA6E4B0\\n"')
|
||||
bp("3fa84fe0", 'printf "AFTER-CALL a8=%08X\\n", a8')
|
||||
bp("3fa853a0", 'printf "CALLER-ERR-RET a8=%08X a11=%08X\\n", a8, a11')
|
||||
bp("3fa853d0", 'printf "CALLER-OK-PATH code=%08X\\n", d@16F0')
|
||||
bp("3fdf0630", 'printf "DISPATCH-READ code=%08X\\n", d@16F0')
|
||||
local n = 0
|
||||
emu.register_frame_done(function()
|
||||
n = n + 1
|
||||
if n >= tonumber(os.getenv("HP_FRAMES") or "700") then print("done "..n); machine:exit() end
|
||||
end, "vt1200-hp-disp")
|
||||
dbg.visible_cpu = cpu
|
||||
dbg.execution_state = 'run'
|
||||
Reference in new issue
Block a user