Skip to content

Display Output

visrealm edited this page Aug 25, 2026 · 3 revisions

The PICO9918 has one video pipeline and two output drivers behind it. The VGA driver produces 640x480 @ 60 Hz progressive for the VGA Dongle, the on-board VGA header and the Digital AV Dongle; the SCART driver produces interlaced RGBs for the SCART AV Dongle. Which one runs is decided once, at boot.

This page covers how that decision is made, and, more importantly, how the firmware lets you change it without ending up staring at a display that cannot show you the configurator.

How the output is chosen

Dongle autodetect

Before anything claims the video pins, the firmware probes for a SCART dongle:

  1. GPIO 0 (HSYNC) is made an output at 12 mA drive strength; GPIO 1 (VSYNC) is made an input with its pull-down enabled.
  2. GPIO 0 is driven high and the firmware waits 1 ms.
  3. GPIO 1 is read. High means the two pins are bridged: a SCART dongle. Low means they are not.
  4. GPIO 0 is released, the pull-down is removed, both pins go back to inputs at 4 mA, and the PIO re-claims them when video starts.

One 1 k resistor is the whole detection mechanism: the same pin pair with and without the SCART dongle

The bridge is the SCART dongle's only component besides its two connectors: a single 1 kΩ resistor between HSYNC and VSYNC. The VGA dongle has no resistors at all: its bill of materials is the FFC connector and the DE-15 socket, and its schematic keeps HSYNC and VSYNC as separate nets, so it reads as "no SCART dongle", as does an empty FFC connector where GPIO 1 simply follows its own pull-down. The Digital AV Dongle likewise runs from the VGA driver; the configurator calls the setting for that timing VGA/HDMI mode for exactly that reason.

The result is resolved into CONF_DISP_DRIVER (config byte 5): 0 = VGA, 1 = NTSC SCART, 2 = PAL SCART. The SCART value comes from the saved SCART mode, so PAL versus NTSC is a setting rather than something the probe can see.

Warning

The probe runs exactly once, on core 0, before the second core is even launched. It is never re-run. Swapping dongles on a powered board will not change the output. Power the host off first.

If diagnostics are enabled, the OUTPUT row of the Diagnostic Overlays shows which driver won: 480P @60, 480I @60 or 576I @50.

The driver preference override

Detection is only consulted when the firmware is asked to detect. CONF_DISP_DRIVER_PREF (config byte 13) decides:

Value Configurator label Behaviour
0 Auto Use the dongle probe (default)
1 VGA/HD Always use the VGA driver, whatever is fitted
2 SCART Always use the SCART driver, whatever is fitted

It lives under Output → Driver in the Configurator, alongside VGA/HDMI mode and SCART mode. Forcing a driver is useful when detection cannot help (driving a SCART display through custom wiring that has no 1 kΩ bridge, for instance) but it is also the one setting that can leave you with no picture at all, which is what the flow below exists for.

Changing the output safely

Four settings can change what comes out of the video connector, and all four are handled specially:

  • Driver (CONF_DISP_DRIVER_PREF)
  • VGA/HDMI mode (CONF_VGA_MODE)
  • SCART mode (CONF_SCART_MODE)
  • Clock frequency (CONF_CLOCK_PRESET_ID)

Saving a change to any of them does not write it to the main configuration. It goes into a 16-byte record in the 4 KB flash sector at 0x1FE000, immediately below the configuration sector at 0x1FF000, and that record carries a state byte: CONFIRMED (0xC0), PENDING (0x9E) or ARMED (0xA0).

How a display output change is applied, and why doing nothing undoes it

What you do, and what you see:

  1. Change the setting in the configurator and save. The new values are written to the pending sector as PENDING; the main configuration keeps its last-confirmed values. The screen (still running the old, known-good settings) shows:

    POWER CYCLE TO TEST NEW CONFIGURATION

  2. Power cycle the host. On boot the firmware finds PENDING, copies the four values over the configuration it just read from flash, rewrites the record as ARMED, and brings up video with the new settings. If they work, you see the new output plus:

    OPEN CONFIGURATOR TO CONFIRM NEW SETTINGS

  3. Run the configurator and answer the prompt. It checks the pending state at startup and, finding ARMED, puts up a popup: Display change OK?

    • Confirm writes the running values to the main configuration sector and erases the pending sector. The change is now permanent.
    • Cancel erases the pending sector without touching the main configuration.
  4. If step 2 gave you nothing (a black screen, an out-of-range message, a monitor that will not sync), you cannot reach step 3, and that is the point. Power cycle again. The firmware finds ARMED, erases the pending sector, and boots on the main configuration's last-confirmed values. Your picture comes back.

Tip

The whole flow reduces to one rule: an unconfirmed display change survives exactly one power cycle. If a new setting leaves you blind, power-cycle twice and you are back where you started. No USB recovery, no reflashing.

Important

Cancel does not restore the old output there and then. It erases the pending record, so the session you are in keeps running the new settings and the next boot returns to the last-confirmed configuration. That is deliberate: reverting live would drop video out from under the configurator you are using.

Three details worth knowing:

  • The pending sector is written before the main configuration, so losing power between the two writes still reverts cleanly rather than leaving a half-applied change.
  • A factory reset, and any configuration rewritten because the firmware was upgraded, take a separate forced path that writes the main configuration directly and erases the pending sector. You are never asked to confirm a change you did not make.
  • The web configurator does not use the flow at all. It generates a UF2 containing both the configuration block and a CONFIRMED pending block, so settings applied over USB take effect on the next boot and stay. A UF2 that wrote only the configuration block would leave a stale pending record behind, and the chosen settings would never appear.

Clock presets

The SCART driver needs a 13.5 MHz pixel clock, which the VGA preset table cannot divide down exactly, so SCART boots from a table of its own:

Preset VGA system clock SCART system clock
0 252 MHz 270 MHz
1 302.4 MHz 324 MHz
2 352 MHz 324 MHz

The preset number is a single saved setting (CONF_CLOCK_PRESET_ID); which table it indexes is decided by the output driver. See Clock Presets for the PLL dividers and core voltages, and Pixel Clock for why 270 and 324 MHz are the numbers.

Because the system clock has to be set before the configuration is read, the boot-clock decision reads the flash blocks directly, and a PENDING or ARMED record outranks the stored configuration. That is what lets a pending change to the driver or the clock preset be tested on the very boot that arms it.

Build-time options

Option Default Effect
PICO9918_ENABLE_SCART=ON yes Both drivers built. The dongle probe, the SCART clock table and the interlaced timing are all compiled in, and the driver is chosen at runtime.
PICO9918_ENABLE_SCART=OFF - VGA only. No probe, no SCART clock table, no RGBs timing; the display mode is fixed to VGA_640_480_60HZ at compile time.

A VGA-only build is tagged in its artifact name with a -vgaonly suffix: pico9918pro-v<version>-vgaonly.uf2. Release firmware is built with SCART support on, so a stock download handles every dongle. See Firmware Configuration Options.

The pending flow itself is not conditional: in a -vgaonly build it still guards the clock preset and the VGA mode, exactly as it guards the driver in a full build.

Related

Clone this wiki locally