pico-ttl2dvi: TTL-naar-DVI Converter op basis van de RP2350
Elke bron wordt vastgelegd op de volledige framerate. De firmware kan automatisch detecteren welke kaart is aangesloten en hierop overschakelen.
Ondersteunde bronnen
| Bron | Datalijnen | Dot clock | Output |
|---|---|---|---|
| MDA / Hercules (16 MHz kloon kristal) | VIDEO + INTENSITY, 2-bit | 16.000 MHz | 4-level grijs |
| CGA, 640-breed modi | RGBI, 4-bit | 14.323 MHz | 16 kleuren |
| Commodore 128 VDC, 80-kolom | RGBI, 4-bit | 16.000 MHz | 16 kleuren |
| EGA, 350-lijn modi | RGBrgb, 6-bit | 17.750 MHz | 64 kleuren |
| EGA, 200-lijn modi | RGBI, 4-bit | 14.161 MHz | 16 kleuren |
De firmware ondersteunt zowel tekst- als grafische modi. CGA en EGA 200-lijn modi maken gebruik van het standaard CGA-palet (inclusief de IBM 5153 "bruin"-correctie). EGA schakelt live tussen de 200- en 350-lijn modi, afhankelijk van de kaart.
Kleurbronnen worden gecodeerd als RGB222, wat resulteert in ongeveer 75% van de volledige helderheid. Verhoog de helderheid van de monitor om dit te compenseren.
Bedrading
Gebruik een DE-9 connector vanaf de kaart, met 330 $\Omega$ weerstanden in serie op elke lijn, aangesloten op de 5V-tolerante ingangen van de RP2350.
| Signaal | DE-9 Pin | GPIO |
|---|---|---|
| VIDEO (MDA) / Secundaire BLAUW (EGA) | 7 | 20 |
| INTENSITY / Secundaire GROEN (EGA) | 6 | 21 |
| ROOD | 3 | 22 |
| GROEN | 4 | 23 |
| BLAUW | 5 | 24 |
| Secundair ROOD (EGA) | 2 | 25 |
| VSYNC | 9 | 26 |
| HSYNC | 8 | 27 |
| GND | 1 | GND |
Bij EGA 350-lijn modi dragen pinnen 2, 6 en 7 het secundaire rood, groen en blauw. In 200-lijn modi werkt de kaart als CGA: pin 6 is INTENSITY en pinnen 2 en 7 worden niet gebruikt. Pin 2 is bij EGA nooit aarde; gebruik uitsluitend pin 1 voor GND.
De DVI-output pinnen zijn afhankelijk van de board-configuratie (cmake/boards.cmake + src/config/board.h); op de standaard Waveshare RP2350-PiZero zijn dit GPIO 32-39.
Directe aansluiting (alleen weerstanden)
Dit is de minimale configuratie. De 330 $\Omega$ weerstand beperkt de stroom naar de clamp-diode van de RP2350-pad; deze diode zorgt voor de "5V tolerantie" en de weerstand houdt het veilig.
videokaart (TTL, 5V) RP2350
─────────────────────── ──────
DE-9 7 VIDEO ─────[ 330Ω ]────────► GPIO 20
DE-9 6 INTENSITY ─────[ 330Ω ]────────► GPIO 21
DE-9 3 RED ─────[ 330Ω ]────────► GPIO 22
DE-9 4 GREEN ─────[ 330Ω ]────────► GPIO 23
DE-9 5 BLUE ─────[ 330Ω ]────────► GPIO 24
DE-9 2 sRED ─────[ 330Ω ]────────► GPIO 25
DE-9 9 VSYNC ─────[ 330Ω ]────────► GPIO 26
DE-9 8 HSYNC ─────[ 330Ω ]────────► GPIO 27
DE-9 1 GND ────────────────────► GND
Door de pad-clamping verbruikt elke actieve lijn enkele mA van de kaart. Zet eerst de Pico aan, daarna de PC; zet bij het uitschakelen eerst de PC uit.
Gebufferd (74HCT541 + weerstanden) – Aanbevolen, through-hole
Een 5V octale buffer tussen de kaart en de Pico. De CMOS-ingangen verbruiken vrijwel geen stroom, waardoor de drivers van de videokaart niet worden belast en een defect aan de Pico-zijde de kaart niet kan bereiken. De 330 $\Omega$ weerstanden verhuizen naar de uitgangen van de buffer, waar 5V logica overgaat in de 3.3V pad.
┌───────── 74HCT541 ────────┐
│ (5V, 100nF over 19-20p) |
DE-9 7 VIDEO ────►│ 2 A1 Y1 18 │──[330Ω]──► GPIO 20
DE-9 6 INTEN ────►│ 3 A2 Y2 17 │──[330Ω]──► GPIO 21
DE-9 3 RED ────►│ 4 A3 Y3 16 │──[330Ω]──► GPIO 22
DE-9 4 GREEN ────►│ 5 A4 Y4 15 │──[330Ω]──► GPIO 23
DE-9 5 BLUE ────►│ 6 A5 Y5 14 │──[330Ω]──► GPIO 24
DE-9 9 VSYNC ────►│ 7 A6 Y6 13 │──[330Ω]──► GPIO 26
DE-9 8 HSYNC ────►│ 8 A7 Y7 12 │──[330Ω]──► GPIO 27
DE-9 2 sRED ────►│ 9 A8 Y8 11 │──[330Ω]──► GPIO 25
│ │
GND ──►│ 1 /OE1 /OE2 19 │◄── GND
GND ──►│ 10 GND Vcc 20 │◄── +5V
└───────────────────────────┘
DE-9 1 GND ─────────────── common ground ──────────────► GND
Beide /OE-pinnen (1 en 19) moeten naar GND. Zorg voor een gemeenschappelijke aarde tussen de kaart, de buffer en de Pico. Gebruik het HCT-onderdeel, niet de gewone HC: de TTL-ingangsdrempels lezen een 5V TTL-high betrouwbaar bij 5V Vcc.
Gebufferd (74LVC245A, geen weerstanden) – Beste methode
Hetzelfde principe, maar gevoed met 3.3V. LVC-ingangen accepteren 5.5V ongeacht de Vcc — de 5V-tolerantie is een ingebouwde eigenschap van deze familie. De kaart kan dus direct worden aangesloten en de uitgangen zijn al 3.3V logica.
┌───────── 74LVC245A ─────────┐
│ (3.3V, 100nF over 10-20p) │
DE-9 7 VIDEO ──►│ 2 A1 B1 18 │────► GPIO 20
DE-9 6 INTEN ──►│ 3 A2 B2 17 │────► GPIO 21
DE-9 3 RED ──►│ 4 A3 B3 16 │────► GPIO 22
DE-9 4 GREEN ──►│ 5 A4 B4 15 │────► GPIO 23
DE-9 5 BLUE ──►│ 6 A5 B5 14 │────► GPIO 24
DE-9 9 VSYNC ──►│ 7 A6 B6 13 │────► GPIO 26
DE-9 8 HSYNC ──►│ 8 A7 B7 12 │────► GPIO 27
DE-9 2 sRED ──►│ 9 A8 B8 11 │────► GPIO 25
│ │
+3V3 ──►│ 1 DIR │ DIR high = A→B
GND ──►│ 19 /OE Vcc 20 │◄── +3V3 (Pico 3V3 pin)
│ 10 GND │
└─────────────────────────────┘
DE-9 1 GND ─────────────── common ground ──────────────► GND
DIR high en /OE low schakelen de richting in naar A→B; beide moeten vastgezet worden en niet zweven. Voed de chip vanaf de 3V3 pin van de Pico — de 5V-tolerantie is afhankelijk van een Vcc van 3.3V.
Naast het weglaten van de weerstanden, verwijdert dit ook de regel over de aan- en uitvolgorde: LVC ondersteunt gedeeltelijke stroomuitschakeling, dus de kaart mag actief zijn terwijl de Pico uitstaat.
Bediening: knoppen en IR-afstandsbediening (optioneel)
Drie drukknoppen en een IR-ontvanger bedienen een menu van één regel op het scherm, zodat de box kan worden afgesteld zonder computer. Beiden zijn optioneel.
| Functie | GPIO | Header pin (Pi layout) |
|---|---|---|
| IR-ontvanger output | 6 | 31 |
| Knop UP (vorige / -1) | 7 | 26 |
| Knop DOWN (volgende / +1) | 8 | 24 |
| Knop ENTER (kort: select, lang: terug) | 9 | 21 |
Drukknoppen (elk naar GND)
┌──── UP ────┐
GND ───┤ ├───────────────────► GPIO 7
└─── o o ───┘
┌─── DOWN ───┐
GND ───┤ ├───────────────────► GPIO 8
└─── o o ───┘
┌── ENTER ───┐
GND ───┤ ├───────────────────► GPIO 9
└─── o o ───┘
IR-ontvanger (KY-022 / VS1838B)
┌───────────┐
│ KY-022 │
│ S ├─────────────────────► GPIO 6
│ VCC ├──────┬──────────────◄ 3V3
│ │ ═<0xE2><0x95><0xAA>═ 100nF
│ - ├──────┴─────────────── GND
└───────────┘
Er zijn geen weerstanden nodig. De firmware activeert de interne pull-ups, dus een knop wordt als "low" gelezen wanneer deze wordt ingedrukt. Sluit knoppen aan op GND, niet op 3V3 met pull-downs: RP2350 erratum E9 kan een input vastzetten (latch) met de interne pull-down bij ~2V.
Voed de IR-ontvanger met 3V3, niet met 5V: de output is pulled up naar de eigen voeding, dus bij 3V3 kan deze direct op de GPIO worden aangesloten. Plaats een 100 nF condensator over de VCC en GND van de ontvanger, direct bij de module. Zonder deze condensator bereikt schakelruis van de video-ingangen de ontvanger via de voeding, waardoor de LED knippert (waargenomen bij EGA 350-lijn modi).
De afstandsbediening moet het NEC-protocol spreken. Om een afstandsbediening te gebruiken:
- Op de box: Menu → Remote → Learn, en volg de aanwijzingen op het scherm met de drukknoppen.
- Via de computer: Registreer de knoppen met
tools/irlearn.py --learn ir.txt, zet de map om in een UF2 mettools/irmap2uf2.py ir.txt, en sleepirmap.uf2naar de BOOTSEL-schijf.
Firmware-updates laten de map intact.
Hoe het werkt
De signaalstroom is als volgt: TTL video ──> [capture] ──> rawbuf ──> [view] ──> framebuffer ──> [video] ──> DVI
- Capture: pio0/core0
- View: core0
- Video: pio1/core1
Geen enkele CPU bevindt zich in het tijdskritische pad per lijn. De PIO wacht op sync-edges; de CPU actueert slechts één keer per frame, tijdens de verticale blanking. Capture en DVI draaien op separate PIO's en cores, zodat ze elkaar niet kunnen blokkeren.
Core 0 voert het werk per frame uit: het wacht op de VSYNC-edge, bepaalt de bemonsteringswindow op basis van de sync-meting, activeert de DMA en de sampler, en reconstrueert het frame met view zodra het frame eindigt. Per lijn lockt de PIO op elke HSYNC-edge en slaat de DMA de samples op, zonder tussenkomst van de CPU.
De bron (kaart descriptor) configureert beide zijden bij het opstarten: capture krijgt de datapinnen, dot clock en standaard bp/phase; video krijgt de DVI raster en encoder.
Per frame:
syncmeet de HSYNC-periode en polsbreedte met een PIO-countdown.capturebepaalt de bemonsteringswindow en een enkele DMA-transfer legt één VSYNC-begrensd frame van ruwe samples vast inrawbuf. De bemonstering is 1x of 2x, afhankelijk van de bron (2x wanneer de dot clock niet dicht genoeg bij een geheel getal van systeemklokken ligt).viewreconstrueert elke lijn, mapt sample-waarden naar grijstinten of RGB222-kleuren, en schrijft het resultaat in de framebuffer.videoop core 1 loopt door de framebuffer, herhaalt rijen voor verticale schaling, voegt de letterbox toe, TMDS-codeert elke scanline en voedt de serialiser continu.
Signaalcontrole en automatische bronselectie: sigcheck controleert de HSYNC/VSYNC-rates. Zodra deze stabiel zijn, kiest detect de bron op basis van de lijnrate en de gemeten dot clock. Als er een andere kaart wordt gevonden, herstart het systeem in die bron.
Modules
| Pad | Rol |
|---|---|
src/config | Board pinnen, DVI pin config, bron-kaart descriptors |
src/capture | PIO sampler + DMA naar rawbuf, per-lijn reconstructie, signaalcontrole |
src/video | Framebuffer, DVI raster tabellen, TMDS encoding op core 1, kleurtabellen |
src/view | Scan converter: verbindt capture en video, beheert display framing |
src/settings | Persistente instellingen in de laatste flash sector |
src/console | USB CDC command console |
apps/ttl2dvi | De applicatie: opstartvolgorde, commandoset, bron-detectie, OSD, knoppen/menu, IR |
src/ir | NEC IR decoder op pio2 |
apps/dvi_test | Standalone DVI testkaart |
extern/dvi | PicoDVI (libdvi) |
tools | Control panel, frame grabber, autotune, IR key maps |
Console
Verbind met de USB seriële poort (115200 baud) en typ help.
source [n]: Selecteer de kaart (herstart)source auto on|off: Automatische bron-detectie (wordt in flash opgeslagen)mode [n]: DVI output raster (herstart)status / state: Signaal en instellingenbp / phase: Capture framing: sampling window, sub-pixel sampling instantdotclock [MHz]: Kaart dot clock, of standaardhpos / vpos: Display positievscale [1..4]: Verticale schaalscanlines on|off|switch: Sla elke tweede lijn over (vscale >= 2)mdalevels: MDA grijstintenslots: Opgeslagen instellingen voor deze bronsave / load / clear: Instellingen slots in flash (8 per bron)default [n|off]: Slot dat bij boot wordt toegepastdetect / measure: Welke bron auto-detect zou kiezen / meet de dot clocktune [apply]: Meet de dot clock en bepaal de phase (auto tune)osd ...: On-screen display;osd liveschakelt live metingen inir on|off / ir map: Print IR remote codes / lijst geladen key mapcapture / fastcap: Dump frame via USBdvi_test: On-screen test patroon
Voorbeeld:
ttl2dvi> source
auto detection: on
0 MDA16 2 data bits @ GP20, 720 px, 16.000 MHz dot, sysclk 256 MHz <- current
1 CGA 4 data bits @ GP21, 640 px, 14.322 MHz dot, sysclk 258 MHz
2 C128 4 data bits @ GP21, 640 px, 16.000 MHz dot, sysclk 256 MHz
3 EGA 6 data bits @ GP20, 640 px, 17.750 MHz dot, sysclk 266.4 MHz, both families
ttl2dvi> source 1
switching to CGA...
Een kaart afstellen (Tuning)
Als het kristal van een kaart afwijkt van de standaardwaarden, kan het beeld flikkeren of verticale balken vertonen. Plaats tekst of een testpatroon op het scherm en:
- Op de box: Menu → Sampling → Auto tune. Het systeem meet de dot clock, bepaalt de phase en biedt de opties Apply, Apply and save, of Cancel.
- Via de console:
tuneprint het resultaat,tune applypast het toe. - Via de computer:
tools/autotune.pydoet hetzelfde via eenfastcapdump.
Auto tune en tune zoeken van -25% tot +33% van de huidige dot clock. Als het resultaat geen geheel getal is van de systeemklok, verschijnt de melding "may shimmer"; het werkt, maar een bron die specifiek voor die klok is gebouwd zou schoner zijn.
ttl2dviPanel
tools/ttl2dviPanel.py is een Tk GUI voor de console (installatie via pip install -r tools/requirements.txt). Het pollt de status elke seconde, zodat de knoppen wijzigingen volgen die via de console zijn gemaakt.
Build
Vereist de Pico SDK (2.3+) en CMake:
mkdir build && cd build
cmake -DTTL_BOARD=pizero ..
make -j
Of via Docker:
docker run -d -it --name pico-sdk \
--mount type=bind,source=${PWD},target=/home/dev \
lukstep/raspberry-pi-pico-sdk:v1.2.0
docker exec -it pico-sdk sh -c \
"cd /home/dev/build && cmake \
-DTTL_BOARD=pizero \
-DPICO_PLATFORM=rp2350-arm-s .. \
&& make -j\$(nproc)"
TTLBOARD selecteert het hardwareprofiel (pizero | pico2dvi). De output is build/apps/ttl2dvi/ttl2dvi.uf2. Upload dit bestand naar de RP2350 in BOOTSEL-modus.
Hardware
Getest op een Waveshare RP2350-PiZero (RP2350B, 48 GPIO, 520 KB SRAM).
Erkenningen
Geïnspireerd door mlorenzati/pico-rgb2hdmi, die analoge RGB naar HDMI converteert op een RP2040. De DVI-output is gebaseerd op PicoDVI door Luke Wren.
Licentie
MIT. extern/dvi bevat PicoDVI en behoudt zijn eigen licentie (zie extern/dvi/LICENSE).
Groetjes,