The signal, and how to check it
OmaCRT sends progressive 15 kHz video to a CRT television through an HDMI-to-RGB converter. This chapter explains the signal levels, modelines and DRM lease used to give each console its own line count.
The launcher, display process and command line require Hyprland. Hyprland lends the television connector to OmaCRT while continuing to manage the desktop outputs. Omarchy is optional.
Omarchy adds the desktop half: the bar widget, the library overlay and the row in its menu. Without it the television works and the command line is the interface. Installing says what the installer skips, On the desktop says what is lost, and The command line is what you use instead.
Interlaced modes are unsupported on the stock-kernel setup described here.
On the tested setup, 480i reaches the converter and the converter stays locked, but the television shows a narrow strip. The progressive modes work. The interlace section below explains the driver limitations.
SCART signal levels
A consumer CRT with a SCART socket needs the following signal levels and a 15 kHz scan rate:
| Pin | Signal | Level |
|---|---|---|
| 15, 11, 7 | Red, green, blue | 0.7 Vpp each |
| 20 | Composite sync | 0.3 to 1 V |
| 16 | RGB blanking | 1 to 3 V, or the set stays on composite and shows black and white |
| 8 | AV switching | 9.5 to 12 V, convenient, not required |
A PC’s VGA output carries separate horizontal and vertical sync at TTL level, five volts. Combine the signals and reduce their level before sending them to pin 20. A direct five-volt connection is five times the maximum level listed above.
Pin 16 selects RGB input. Without a volt or two on this pin, the television stays in composite mode and can show the picture in monochrome. Check this pin if an RGB picture appears black and white.
The nominal line rates are 15.734 kHz for NTSC and 15.625 kHz for PAL. These are roughly half the minimum horizontal frequency of a VGA monitor. The progressive timings here use 262 or 312 total lines per frame. Increasing the horizontal pixel count does not change that requirement.
Graphics output constraints
The signal path has three constraints.
There is no analogue output left. The last AMD card with an analogue path through DVI-I was the R9 380X. Everything since is digital only, so something outside the card has to convert.
Converters refuse the clock. 320 by 240 at 15 kHz needs a pixel clock around 6 or 7 MHz, and almost every active DisplayPort to VGA adapter refuses anything below about 25 MHz. The exceptions are the Realtek RTD2166 and its successor the RTD2168, which take roughly 8 to 210 MHz and have no automatic deinterlacer. The arcade community names those two chips for that reason.
HDMI’s TMDS link has a 25 MHz minimum pixel clock, and the driver rejects HDMI modes below it. A DisplayPort path can use an RTD2166 adapter, a kernel with the 15 kHz patches and an emulator running on KMS. The next section describes the HDMI path used here.
The converter is the monitor the card sees
The graphics card sees the converter as an HDMI monitor. A converter that accepts arbitrary timings can receive a link above the 25 MHz minimum and produce a 15 kHz analogue signal for the television.
The mode the card programs is therefore wide, with a high clock and a long line:
NTSC 72 3520 3781 4119 4577 240 242 245 262 -hsync -vsync
PAL 72 3520 3740 4078 4608 288 291 294 312 -hsync -vsync
For the NTSC modeline, divide the 72 MHz pixel clock by the total line length of 4577 pixels. The result is 15.731 kHz. Dividing again by 262 lines gives 60.04 Hz.
The 3520-pixel active width is a super resolution, a technique used in arcade setups. It gives the emulator room to map a console’s 256- or 320-pixel image across a wide output. The television displays that signal in its 4:3 frame. The 240-line height preserves one output scanline per game line.
Both modelines carry the same active width and the same shape, so a game keeps its size when the standard changes. Only the line count and the totals differ.
The pixel clock is 72 MHz on both. That is a limit of the converter rather than a preference, and The converter gives the measurement behind it.
The refresh rate a program wants
OmaCRT builds a program’s field rate into the timing. It does not adjust the rate while the program runs.
The field rate is the pixel clock divided by the total line length and then by the total number of lines. OmaCRT moves both totals to reach the rate the program asks for, and holds the line rate within four parts per thousand while it does. A European console asking for 49.70 Hz is reached to within 0.003 Hz.
Adaptive sync is the other way to reach a rate, and it is off by default. It works by changing the length of each field, and a television’s vertical oscillator follows what it is given. On one still menu the field measured 16.655 to 16.846 ms with adaptive sync on, and 16.654 to 16.657 ms with it off. Set output.vrr to turn it back on for a multisync monitor, which has no such oscillator to disturb.
One mode per console
A modeline includes sync positions and blanking intervals as well as resolution and refresh rate. wlr-output-management only carries width, height and refresh rate, so it cannot express the full timing.
DRM leasing lets a Wayland compositor hand a connector to another application. The protocol was developed for virtual reality headsets. OmaCRT uses it to control the television output and program timings that the hardware accepts. Hyprland keeps the other outputs.
The process holding the lease can change modes between games while the desktop continues running. Progressive mode changes require neither a patched kernel nor root access, and the user stays in the same desktop session.
Interlace limitations
The tested stock-kernel setup does not produce working interlaced output.
On a Radeon RX 7700 XT, Navi 32 with the DCN 3.2 display engine, on a stock kernel, asking for 480i succeeds. The modeset returns without error, the converter keeps its lock, the status readout says 3520x480 at 59.927 Hz, and the television shows a narrow image in the middle of a black screen.
Nothing rejects the mode. It is programmed with interlaced timings and then scanned out progressively, which at a 525 line vertical total works out at 29.96 Hz, and no television will lock to that.
The driver analysis identified five software limitations between the modeline and interlaced output:
- The interlace flag is never copied out of the mode into the timing structure, so everything downstream believes the timing is progressive.
- The timing validator returns false for anything interlaced, under a comment saying interlacing is temporarily blocked until it is supported.
- The register that enables interlacing is missing from the per-ASIC tables for DCN 3, although the code that writes it is already there and AMD's own published headers carry the address.
- The validation model doubles a ratio for interlaced timings on an ASIC that does not claim to support them, which then fails a later check.
- A flag on the scaler's line buffer is never set from the timing.
Patches for all of it are maintained in the open, at https://github.com/D0023R/linux_kernel_15khz, tracking Calamity's original work from GroovyMAME and Switchres. This project does not patch the kernel. Interlace is off, 480 line consoles are shown at 240p instead, and that is why a line count per console exists.
This affects 480-line systems such as the Dreamcast, Naomi and GameCube. They use 240p as a fallback. Systems that already draw at 240p retain their vertical resolution.
Working interlace would preserve more vertical detail in text and menus on those systems. Alternating fields also introduce visible shimmer, which some people find less comfortable than 240p.
Tested hardware
| Part | Here | What else works |
|---|---|---|
| Graphics card | AMD Radeon RX 7700 XT, Navi 32, DCN 3.2, on amdgpu | Any AMD card on amdgpu: the leasing and the timings are kernel side. Nvidia's proprietary driver offers no leasable connectors. Intel untested |
| Converter | HDMI in, RGB on SCART out, sync mode selected over I2C, audio on the same connector | Anything that takes HDMI and puts RGB on SCART or VGA. On a DisplayPort path, an RTD2166 or RTD2168 adapter and a separate sync combiner |
| Sync | Handled inside the converter | On a VGA path: a VideoAmp, a sirMagb F-15, a UMSA, a VGA2SCART. Never a passive VGA to SCART cable, which has no shielding and a weak sync |
| Television | A Bang & Olufsen BeoCenter 1, over SCART RGB | Any 15 kHz set with an RGB input, PAL or NTSC |
What to buy has the three paths priced, including the fixed mode converters that need no leasing and no patches and cannot give a console its own line count.
Checking the signal path
Check the software and graphics card before buying a converter or television. The development checks were performed in this order:
- Switchres, dry, for the modelines:
switchres 320 240 60 -c -m ntsc. No hardware at all. - A modeline applied to a DisplayPort output with an ordinary monitor attached. The monitor will say the signal is out of range, the correct answer, and the driver's own log says whether it took the mode. This tests the graphics card with no television in the room.
- The converter, on the television, showing the kernel console.
- The lease: the connector marked as not a desktop, offered, taken, and the mode programmed by a process of your own.
- An emulator as a client of that process, with the line count following the console.
- Interlace, where a stock kernel stops.
References
The pin levels are from Martin Hinner's SCART reference at http://martin.hinner.info/vga/scart.html. The modelines were generated with Switchres, https://github.com/antonioginer/switchres, and measured on the set described above. The list of graphics cards, converters and sync solutions that work is maintained by the Batocera CRT project at https://github.com/ZFEbHVUE/Batocera-CRT-Script/wiki. The interlace patches and the discussion around them are at https://github.com/D0023R/linux_kernel_15khz.