Skip to content

video: analog H-size (CRT width stretch) via 54 MHz retimer - #6

Open
asturur wants to merge 11 commits into
masterfrom
crt-hsize
Open

asturur wants to merge 11 commits into
masterfrom
crt-hsize

Conversation

@asturur

@asturur asturur commented Sep 28, 2026

Copy link
Copy Markdown
Member

Adds an analog horizontal size control for the native CRT output (NTSC/PAL progressive), phase 1 of ZaparooProject/zaparoo-frontend#473.

  • 54 MHz video master: pll_video54 replaces the 27 MHz pll_video so the retimer gets 8 clocks per progressive pixel (4 per 480i). Pixel enables become /8 and /4; pixel rates and all line/field timing are unchanged. menu.sdc's async clock group follows the new PLL path.
  • zaparoo_hretime wired into the analog path in sys_top after the VGA OSD, feeding csync/YC/RGB and direct video; the pre-OSD HDMI/ascal tap is untouched. A 4-flop CE delay mirrors the OSD's fixed pipeline. Two fixes to the prototype: skew-free bypass (HS/VS latched with data/DE) and one extra buffered pixel of shrink start margin (odd scales corrupted the line tail via a pop the cycle after its push, before the registered RAM read settled).
  • Interim word2 control beat: the per-vblank poll reads two beats; word2 (bytes 0x08-0x0B) carries magic 0x5A52 and a signed h_size clamped to -8..+2, written only by Main (frontend words 0/1 untouched, legacy writers imply size 0). Contract documented in the reader header; the deferred v3 protocol replaces it wholesale.
  • 480i always bypasses with the saved progressive value preserved (zaparoo_hsize_map, exhaustively tested).
  • Tests: full suite green locally (Icarus 13, arm64 image), including new hsize_map_tb and both retimer TBs now registered in tb/run.sh; reader TB covers word2 decode, clamps, wrong magic, stopped writer and word1-gating.

Pairs with ZaparooProject/Main_MiSTer branch crt-hsize (OSD "H size" row, word2 writer, TOML persistence, yc.txt MENU override removal). Old Main + new Menu = size 0; new Main + old Menu = control ignored.

Hardware qualification on the CRT is still pending: size-0 baseline vs 27 MHz build, -8..+2 sweep on NTSC/PAL, persistence across respawn/reboot, 480i bypass, YC color lock, direct video.

🤖 Generated with Claude Code

asturur and others added 5 commits September 28, 2026 20:37
pll_video54 (1350 MHz VCO / 25, exact) replaces the 27 MHz pll_video so the
analog H-size retimer gets 8 master clocks per progressive pixel (4 per
480i pixel). Pixel enables become /8 progressive and /4 480i; pixel rates,
line lengths and field timing are unchanged, and the full RTL test suite
passes with the doubled clock. menu.sdc's async clock group follows the new
PLL instance path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bypass path now latches HS/VS with data/DE so unity and 480i stay skew-free.
Shrink start margin gains one buffered pixel: extra_px floors the fractional
lead, and odd scales let the reader pop a slot the cycle after its push,
before the registered RAM read settled, corrupting the line tail. The TB now
sweeps every UI step (-8..-1, +1, +2) plus bypass, and both retimer TBs run
from tb/run.sh (with the hsize map TB).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The per-vblank poll reads two beats at 0x3A000000: beat 2's low word is
[31:16] magic 0x5A52, [7:0] signed h_size, clamped to -8..+2, 0 without the
magic or a live word1. Written only by Main; the frontend owns words 0/1
untouched. Two-flop synced out of native_video_top as vga_h_size.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
UI 0 = unity = retimer off; positives shift down one for hretime's
zero-skip scale; 480i always bypasses while the stored progressive value
survives. Exhaustive TB including the 480i-bypass-with-nonzero-size rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
zaparoo_hretime sits after the VGA OSD, feeding csync/YC/RGB and direct
video under the original vga_*_osd names; the pre-OSD HDMI/ascal tap is
untouched. A 4-flop CE delay mirrors the OSD's fixed pipeline so CE and
data keep the phase scanlines guarantees. Controls ride a new Menu-fork
emu sideband (CLK_VIDEO domain, quasi-static).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 666b6251-ff74-4448-9385-4ab9e5bbda73
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

asturur and others added 6 commits September 29, 2026 00:13
At the 54 MHz video clock a simulated frame costs about 8 s of CI CPU, and
phases 0-9 together blew the 600 s timeout three checks from the end. The
default compile now runs phases 0-5 and -DREADER_TB_PART2 runs phase 0 plus
phases 6-9 from a cold reset (the first publish after a writerless reset is
trusted, so part 2 needs no earlier phases). Phase 9 waits drop from three
frames to two: word2 latches at the next per-frame poll.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The OSD derives its dot width as floor(DE_width/512) in raw clocks: 2 of a
4-clock pixel at 27 MHz, but 5 of an 8-clock pixel at 54 MHz. The 5:8 beat
resamples the glyphs, making strokes alternate width on the CRT. A new
FIXED_PIXSZ parameter (default 0 = keep measuring, HDMI instance unchanged)
pins the analog instance to 4 clocks per dot, restoring the 27 MHz look:
half a progressive pixel, one 480i pixel.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The OSD draws half-pixel glyph strokes (256 dots across 128 progressive
pixels). A pixel-rate CE into the retimer kept one of the two dots per
pixel and decimated the font, bypassed or not, which is what showed on the
CRT at every H size. The retimer now samples at a constant clk_vid/4:
one 480i pixel, or one OSD dot, so the OSD survives intact and stretches
with the picture. Base is 4 clocks per sample in every mode (the proven
480i cadence, min 3 clocks per registered RAM pop at -8); a progressive
line is 704 samples, worst shrink lead 89 of 128 FIFO entries; stretch
percentages are unchanged and the mode sideband port is gone (480i gating
already lives in zaparoo_hsize_map). hretime_tb reworked to the 704-dot
NTSC geometry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Word2 bits 15:8 carry a signed v_size, clamped to -32..0: -N adds N blank
lines per progressive frame, floor(N/2) ahead of the sync and the rest
behind it, so the picture shrinks by lowering the frame rate (262+N NTSC,
312+N PAL, down to about 53.5/45.4 Hz at N=32). Active lines, sync width
and all horizontal timing are untouched; 480i forces N=0 at the timing
latch and keeps its exact 262.5-line fields. Blank lines trigger no DDR
reads, and the setting commits only at the frame wrap like the other trims.

Timing TB proves the exact totals, odd-N split, clamp, offset interaction
and 480i immunity; reader TB part 2 covers the decode, clamp and
positive-value rejection.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This reverts commit df9dc75. The frame-rate shrink is invisible on TVs
with frequency-compensated vertical deflection until the standard
detector falls out of its ~10% lock window (at -27 lines), where the
height snaps instead of scaling. Not useful as a control; analog H size
stays. Word2 byte [15:8] returns to reserved-0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment-only: the frontend writes the saved h_size into word2 like it
owns word1's offsets, and Main's OSD save respawns it so the writers
never disagree. No logic change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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