Skip to content

feat(reu): auto-provision the U64 REU for runs that need it#45

Merged
kfox merged 1 commit into
mainfrom
feat/auto-provision-reu
Jun 25, 2026
Merged

feat(reu): auto-provision the U64 REU for runs that need it#45
kfox merged 1 commit into
mainfrom
feat/auto-provision-reu

Conversation

@kfox

@kfox kfox commented Jun 25, 2026

Copy link
Copy Markdown
Owner

What

The REU-staged audio/video paths required the user to manually enable the REU in the U64's F2 menu first, and --doctor errored when it was off. This makes c64cast provision the REU itself.

When a run hard-requires the REU — [audio].use_reu_pump, or an explicit [video].use_reu_staged = true (the same _wants_reu condition --doctor checks) — cli.build_stack now PUTs RAM Expansion Unit = Enabled + REU Size = 16 MB over the Ultimate REST config API at startup. The change is:

  • Live — the firmware applies it immediately via its effectuate hook (no reboot). Verified in the 1541ultimate source: the PUT handler's at_close_config() calls effectuate() only.
  • Volatile — never saved to flash, so it reverts on the next power-cycle even if teardown is missed. teardown_stack also restores the captured original explicitly.

The default use_reu_staged = "auto" is deliberately left alone — it self-heals to the host-DMA double-buffer path (also tear-free), so no machine config is mutated for it.

Why 16 MB

It covers every c64cast REU offset — the audio ring near 1 MB and the video staging region near 14 MB (modes.REU_VIDEO_BITMAP_COLOR_BASE). This was an unstated requirement: a 2 MB default REU would have silently wrapped the video-staging writes. 16 MB is the max and is FPGA-backed, so it's free.

Changes

  • api.put_config_item()PUT /v1/configs/<cat>/<item>?value=<v> (the same route the existing _diaglib.rest_set_config shim uses). Capability-gated default on the backend ABC (Ultimate-only; gated on profile.supports_reu).
  • doctor.provision_reu / restore_reu / read_reu_config — the policy + REST reads. Gated on auto_reu, supports_reu, a probe being allowed (never writes config it can't first read back), and the hard-requirement check.
  • [ultimate64].auto_reu (default true) — set false to manage the REU yourself.
  • --doctor downgrades the REU-disabled diagnostic from error → ok when auto_reu will enable it; still errors when auto_reu = false.
  • Corrects the _diaglib.rest_set_config docstring: the single-item PUT is live + volatile, not a flash write (it previously claimed "Persists to flash").
  • Docs: CLAUDE.md, annotated example TOML, regenerated c64cast.schema.json.

Verification

  • HW-verified end-to-end on a real Ultimate 64: live PUT applies; load_from_flash reverts it (confirming volatility); provision_reu enables + sizes to 16 MB; restore_reu puts the originals back; machine restored + reset. All checks PASS.
  • Unit tests for the provisioner gating, restore, read, and the put_config_item route shape (tests/test_doctor.py, tests/test_api.py); existing doctor REU-error test split into auto_reu on/off cases.
  • make check green: ruff, mypy --strict, pyright (0 errors), 1606 tests.

…that need it

The REU-staged audio/video paths ([audio].use_reu_pump, explicit
[video].use_reu_staged = true) required the user to manually enable the
REU in the F2 menu first — and --doctor errored when it was off. Now
c64cast provisions it itself: at startup, for a run that hard-requires
the REU, it PUTs "RAM Expansion Unit" = Enabled + "REU Size" = 16 MB over
the Ultimate REST config API. The change is LIVE (the firmware applies it
via effectuate, no reboot) and VOLATILE (never saved to flash, so it
reverts on the next power-cycle); teardown restores the original.

- api.put_config_item(): PUT /v1/configs/<cat>/<item>?value=<v> (the same
  route the HW-validated _diaglib.rest_set_config uses). Capability-gated
  default on the backend ABC.
- doctor.provision_reu/restore_reu/read_reu_config: the policy + REST
  reads. Provisioning is gated on auto_reu, profile.supports_reu, a probe
  being allowed, and the _wants_reu hard-requirement (use_reu_pump or
  explicit use_reu_staged = true). The "auto" default is left alone — it
  self-heals to host-DMA double-buffer (also tear-free) without touching
  machine config. Always sizes to 16 MB (covers the audio ring near 1 MB
  and the video staging region near 14 MB; FPGA-backed, so free).
- [ultimate64].auto_reu (default true) controls it; false = manage the
  REU yourself.
- --doctor downgrades the REU-disabled diagnostic from error to ok when
  auto_reu will enable it; still errors when auto_reu = false.
- cli.build_stack runs the provisioner before _resolve_reu_available (so
  that probe sees the now-enabled REU); teardown_stack restores it.
- 16 MB covers every c64cast REU offset, which the docs never spelled out
  (the video staging region tops out near 14 MB — a 2 MB default REU would
  have silently wrapped).

Also corrects the _diaglib.rest_set_config docstring: the single-item PUT
is live + volatile, NOT a flash write (verified in route_configs.cc +
config.h at_close_config, which calls effectuate only).
@kfox kfox merged commit 46cc06d into main Jun 25, 2026
6 checks passed
@kfox kfox deleted the feat/auto-provision-reu branch June 25, 2026 01:13
@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.78082% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.76%. Comparing base (4e1762a) to head (fe5662b).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
c64cast/doctor.py 95.08% 2 Missing and 1 partial ⚠️
c64cast/cli.py 33.33% 2 Missing ⚠️
c64cast/backend.py 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #45      +/-   ##
==========================================
+ Coverage   79.69%   79.76%   +0.06%     
==========================================
  Files          68       68              
  Lines       12947    13020      +73     
  Branches     1911     1924      +13     
==========================================
+ Hits        10318    10385      +67     
- Misses       2190     2195       +5     
- Partials      439      440       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

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