Skip to content

firmware: WriteC64Spans runs beside REU emulation - #92

Draft
kfox wants to merge 3 commits into
SensoriumEmbedded:mainfrom
kfox:firmware-reu-keeps-dma-job
Draft

kfox wants to merge 3 commits into
SensoriumEmbedded:mainfrom
kfox:firmware-reu-keeps-dma-job

Conversation

@kfox

@kfox kfox commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

What changed and why

With Special IO set to an REU, WriteC64Spans was refused at its token ("REU emulation is running") for as long as the handler was installed. A host streaming to an NMI sample player then fell back to whole WriteC64Mem halts, which drop NMIs: the audio stutters, and it plays cleanly as soon as the REU is turned off.

The refusal guarded a real race. DirectREU() runs from isrPHI2 when the C64 starts a transfer, and it drives the bus through the same DMA_* state SetUpDMA leaves for a host job. The C64 keeps running between a job's setup and its transfer: the safe-start window of every PerformDMA (WriteC64Mem and ReadC64Mem included, which were never refused), and the whole wait for a locked slice's sample store. A transfer started there moved the host's bytes to the REU's address and length.

  • DirectREU() now saves the job's DMA_RnW, DMA_FixC64Addr, DMA_Length, DMA_Count and DMA_StartAddr, and restores them before it returns.
  • An immediate REU transfer no longer clears fBusSnoop when another owner holds it. It used to drop the sample store watch a locked job runs on.
  • WriteC64SpansCommand refuses only a paused C64 now. docs/ControlComms.md says so, and notes that earlier firmware also refused while REU emulation was set up.

What to look at

The save in DirectREU() runs before its PHI2-falling wait on the IO2 write cycle, next to the DMA_* setup that was already there. It is five loads.

How it was verified

  • npm test: 355 of 355 pass.
  • The new reu_trpage_harness tests drive an REU transfer through the IO2 handler. The job-state test fails if any one of the five restores is removed (tried one at a time). The bus-snoop test fails with the old unconditional clear.
  • Host tests only, not hardware tested. The firmware builds for both targets come from CI.

kfox added 3 commits November 6, 2026 12:38
DirectREU drives the bus through the same DMA_* state SetUpDMA leaves
for a host DMA job. The C64 keeps running after a job is set up and
before its transfer starts (WriteC64Mem's and ReadC64Mem's safe-start
window, and the whole wait for a locked WriteC64Spans slice's sample
store), so a program that starts an REU transfer then moves the job's
bytes to the REU's C64 address and length instead of the host's.
DirectREU now puts the job state back before it returns.
It was refused whenever REU emulation was set up, because an REU
transfer between slices overwrote the job's DMA state. The previous
commit closes that, so the refusal only cost the slicing: with Special
IO set to an REU, a host streaming to an NMI sample player fell back to
whole WriteC64Mem halts, which drop NMIs and make the audio stutter.
A paused C64 is still refused, since the first slice would resume it.
An immediate REU transfer cleared fBusSnoop whoever held it, so the sample store watch a locked WriteC64Spans job runs on was dropped by the first transfer the C64 started, and every later slice waited out its gap and started unlocked. It now clears the slot only when its own FF00 check holds it.

The job-state test set up a write job and ran a C64-to-REU... transfer that also left DMA_RnW false, so dropping the DMA_RnW restore passed; the job is now a read.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant