PicoDVI: Microcontroller DVI Output on RP2040 and RP2350
Bitbanged DVI on the RP2040 Microcontroller
At a glance
- What is it?
- PicoDVI generates DVI video directly from RP2040 and RP2350 microcontrollers using PIO, DMA, core-local processing, and a custom output circuit. It suits embedded display experiments, but its documented hardware is not fully DVI-compliant and the current repository has no tagged releases.
- Who is it for?
- Adopt PicoDVI when an RP2040 or RP2350 project specifically needs microcontroller-driven DVI and the custom board is acceptable. Do not adopt it as a general HDMI display solution or as a fully compliant DVI PHY without accounting for the hardware limits.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 83 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What PicoDVI solves on RP2040 and RP2350
PicoDVI addresses a specific embedded display problem: producing a digital video stream from a microcontroller without placing an FPGA, transmitter board, or other dedicated video controller between it and a display. The original design targets the RP2040 and drives a DVI connector from general-purpose GPIO pins. The current preview also includes RP2350 support, with RISC-V assembly ported for Hazard3 and Cortex-M33 assembly adjusted for performance.
The project is aimed at developers experimenting with small graphics systems, retro-style displays, sprite rendering, tiled graphics, and direct video output from a microcontroller. Its README documents a 640x480 RGB565 image at 640x480p 60 Hz using 264 kB of SRAM and two Cortex-M0+ processors on the RP2040. It also mentions enough memory for a QVGA framebuffer and a separate rendering core while the other processor services video output.
This is not a conventional display driver with a general-purpose monitor abstraction. The repository centers on a specific hardware design, a timing and TMDS implementation, and example firmware. That distinction matters for adoption. PicoDVI can fit a project that needs direct DVI timing, but it is a poor fit for an application that expects a portable HDMI or display-port driver across arbitrary boards.
How PicoDVI assembles and emits the video stream
The documented RP2040 architecture divides the work between PIO, DMA, and the processors. The README states that PIO sends data streams at the system-clock rate while also driving a related one-tenth-rate clock. This gives the output path a dedicated mechanism for producing serial data without making a general-purpose CPU execute every pin transition directly.
DMA helps generate synchronization and blanking patterns on demand rather than storing every recurring pattern in memory. Video data enters the pipeline as RGB565 pixel content. The TMDS encoder converts the pixels and control information into serial transitions, while a core-local hardware resource and a specialized encoding method perform pixel-doubled encoding during output. The README estimates that this work consumes around 60 percent of an M0+ core at 252 MHz for 640x480p 60 Hz.
The RP2350 preview changes part of that path. RGB encoding uses the SIO TMDS encoders by default, while `DVI_USE_SIO_TMDS_ENCODE=0` selects the software-configured alternative. The key setting is defined in `software/libdvi/dvi_config_defs.h`. Assembly in `libdvi` has been ported to RISC-V and tuned for Hazard3, while some Cortex-M33 paths were adjusted for performance. Parts of `libsprite` have also been ported to RISC-V, although the README limits that claim to running the stock demos.
This architecture explains why PicoDVI is specialized. It combines timing generation, data movement, pixel encoding, graphics generation, and a high-speed physical output design. A project expecting to replace any component with an unrelated display subsystem would need to understand those interfaces rather than treating PicoDVI as a simple monitor enumeration library.
Building the firmware with CMake and the Pico SDK
The documented build starts from the `software` directory. The reader must already have the Pico SDK available locally because the configuration passes its filesystem path through `PICO_SDK_PATH`. The example selects the Cortex-M33 RP2350 target. The README also states that `PICO_PLATFORM` can be set to `rp2350-riscv`.
Use the following commands exactly as documented to create the build directory and configure CMake:
cd software
mkdir build
cmake -DPICO_SDK_PATH=/path/to/sdk -DPICO_PLATFORM=rp2350 -DPICO_COPY_TO_RAM=1 -DDVI_DEFAULT_SERIAL_CONFIG=pico_sock_cfg ..Replace `/path/to/sdk` with the local Pico SDK path before running the configuration command. The repository identifies `software/include/common_dvi_pin_configs.h` as the list of available DVI configurations. Changing `DVI_DEFAULT_SERIAL_CONFIG` therefore affects which predefined serial and pin configuration the build selects, so it should not be changed casually when following the first build.
After configuration, compile with Make. The `-j$(nproc)` option passes the number of available processors to parallel compilation:
make -j$(nproc)A successful build produces firmware for the configured examples. The repository provides demo applications under `software/apps`, but the README excerpt does not give commands for selecting or building one specific application, so the exact target-selection interface cannot be confirmed here.
Flashing a first PicoDVI UF2 demo
The README names `software/apps/tiles_and_sprites/tiles_and_sprites.uf2` as an example output. It gives the following copy command, but does not include a destination or explain whether it assumes a mounted RP2040 drive:
cp apps/tiles_and_sprites/tiles_and_sprites.uf2Because that command contains only one path, it does not provide a complete standalone transfer workflow. The broader instructions state that a binary should be flashed and that UF2 data files can be dragged onto the target board. The practical route described by the repository is therefore to build the firmware, locate the generated UF2, and drag that file onto the board's connected removable storage device in its BOOTSEL mode.
The `vista` demo requires an additional hardware-dependent data file. The original RP2040 file is `software/assets/vista_data_rp2040.uf2`, which the README says can be dragged onto RP2040 and RP2350 A0. The file `software/assets/vista_data_rp2350.uf2` is intended for RP2350 A1 and later because it differs in family IDs. Selecting the wrong data file can prevent the demo data from loading, even when the main firmware itself was built for the correct processor family.
The README does not document a command-line flash utility, boot process, serial configuration, or expected monitor prompt. A first user therefore needs to follow the board's BOOTSEL procedure and use the Pico SDK environment already required by the build.
Electrical compliance and the limits of the custom DVI board
PicoDVI's custom board is the most consequential adoption constraint. The revised output circuit uses resistors and reduces GPIO drive strength and slew. The README reports eye-mask results for VGA-rate 60 Hz operation at 252 Mbps and for 720p30 at 372 Mbps. It also notes that 720p30 can require GPIO overvoltage on typical RP2040 silicon and says that this can be enabled with a register write.
Those results do not make the board fully compliant with the DVI specification. The stated issue is the high-level voltage offset caused by the MCU's CMOS output. The allowed common-mode tolerance is narrow, and the README explains that more than roughly 60 mV between the source and sink 3.3 V rails can move the output outside the cited plus or minus 10 mV range. A differential receiver may tolerate that offset in practice, but the output remains outside the specification.
Cable and sink behavior also matter because the output relies on general-purpose digital pads and a custom coupling or termination network. The README does not document operation across arbitrary DVI monitors, cable lengths, adapters, or HDMI conversion devices. It also does not document hotplug detection or EDID handling. PicoDVI should therefore be judged as a specific research and embedded display design, not as a universally interoperable monitor interface.
The original debugging history offers useful engineering context. The developer reduced the system clock to 12 MHz for probing and used a UART substitution PIO program to inspect the TMDS stream with a logic analyser. Those were debugging techniques for the custom implementation, not general modes documented for normal user operation.
RP2350 porting scope and upgrade considerations
The RP2350 support is explicitly labeled a preview. The repository is not archived, and its last push was on 2026-08-01, which indicates recent repository activity at that date. However, it has no GitHub releases, so the README's porting notes are the available basis for understanding the current state rather than a stable release history.
Several upgrade costs are visible. Low-level video code depends on architecture-specific assembly, and the preview contains separate work for Arm and RISC-V execution. `libdvi` changes cover TMDS encoding and instruction paths, while `libsprite` is only described as ported far enough for the stock demos. Moving from RP2040 to RP2350 also requires choosing the right platform, considering whether the SIO TMDS encoder is appropriate, and selecting the correct `vista` data file for the precise board revision.
The default RP2350 configuration selects SIO TMDS encoding. A developer relying on the older software path must define `DVI_USE_SIO_TMDS_ENCODE=0` and consult `software/libdvi/dvi_config_defs.h`. That switch is meaningful because encoder selection affects a timing-sensitive output path.
The project uses the BSD-3-Clause license. The repository provides a `LICENSE` file, but this review does not interpret legal obligations. Users still need to inspect that file and any notices in copied or modified source files when redistributing firmware or derived hardware designs.
Editorial conclusion
Adopt PicoDVI when an RP2040 or RP2350 project specifically needs microcontroller-driven DVI and the custom board is acceptable. Do not adopt it as a general HDMI display solution or as a fully compliant DVI PHY without accounting for the hardware limits. Before committing, build the target demo for the exact RP2040 or RP2350 family, verify the selected pin configuration, and test the resulting UF2 with the intended display and cable. For this repository, the first concrete adoption check is whether `software/include/common_dvi_pin_configs.h` contains a configuration matching the board and connected DVI lanes.
Frequently asked questions
Which microcontrollers does PicoDVI support?
The original project targets the RP2040, while the current preview adds RP2350 support for RISC-V Hazard3 and Cortex-M33 execution paths.
How do I build PicoDVI firmware?
The README uses CMake with `PICO_SDK_PATH`, `PICO_PLATFORM`, `PICO_COPY_TO_RAM`, and `DVI_DEFAULT_SERIAL_CONFIG`, then compiles with `make -j$(nproc)` from the build directory.
Which UF2 file should I use for the vista demo?
Use `software/assets/vista_data_rp2040.uf2` for RP2040 and RP2350 A0, or `software/assets/vista_data_rp2350.uf2` for RP2350 A1 and later. The difference is the family ID stored in the file.
Is the PicoDVI hardware fully DVI-compliant?
No. The README says the output circuit is not fully compliant because its CMOS logic level can fall outside the specified common-mode range, although a differential receiver may tolerate the offset in practice.
Does PicoDVI use the RP2350 SIO TMDS encoder?
Yes, RGB encoding uses the SIO TMDS encoders by default on RP2350. Defining `DVI_USE_SIO_TMDS_ENCODE=0` disables that default behavior.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wren6991-picodvi)Was this useful?