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

BronDatalijnenDot clockOutput
MDA / Hercules (16 MHz kloon kristal)VIDEO + INTENSITY, 2-bit16.000 MHz4-level grijs
CGA, 640-breed modiRGBI, 4-bit14.323 MHz16 kleuren
Commodore 128 VDC, 80-kolomRGBI, 4-bit16.000 MHz16 kleuren
EGA, 350-lijn modiRGBrgb, 6-bit17.750 MHz64 kleuren
EGA, 200-lijn modiRGBI, 4-bit14.161 MHz16 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.

SignaalDE-9 PinGPIO
VIDEO (MDA) / Secundaire BLAUW (EGA)720
INTENSITY / Secundaire GROEN (EGA)621
ROOD322
GROEN423
BLAUW524
Secundair ROOD (EGA)225
VSYNC926
HSYNC827
GND1GND

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.

FunctieGPIOHeader pin (Pi layout)
IR-ontvanger output631
Knop UP (vorige / -1)726
Knop DOWN (volgende / +1)824
Knop ENTER (kort: select, lang: terug)921

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 met tools/irmap2uf2.py ir.txt, en sleep irmap.uf2 naar 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:

  1. sync meet de HSYNC-periode en polsbreedte met een PIO-countdown.
  2. capture bepaalt de bemonsteringswindow en een enkele DMA-transfer legt één VSYNC-begrensd frame van ruwe samples vast in rawbuf. 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).
  3. view reconstrueert elke lijn, mapt sample-waarden naar grijstinten of RGB222-kleuren, en schrijft het resultaat in de framebuffer.
  4. video op 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

PadRol
src/configBoard pinnen, DVI pin config, bron-kaart descriptors
src/capturePIO sampler + DMA naar rawbuf, per-lijn reconstructie, signaalcontrole
src/videoFramebuffer, DVI raster tabellen, TMDS encoding op core 1, kleurtabellen
src/viewScan converter: verbindt capture en video, beheert display framing
src/settingsPersistente instellingen in de laatste flash sector
src/consoleUSB CDC command console
apps/ttl2dviDe applicatie: opstartvolgorde, commandoset, bron-detectie, OSD, knoppen/menu, IR
src/irNEC IR decoder op pio2
apps/dvi_testStandalone DVI testkaart
extern/dviPicoDVI (libdvi)
toolsControl 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 instellingen
  • bp / phase: Capture framing: sampling window, sub-pixel sampling instant
  • dotclock [MHz]: Kaart dot clock, of standaard
  • hpos / vpos: Display positie
  • vscale [1..4]: Verticale schaal
  • scanlines on|off|switch: Sla elke tweede lijn over (vscale >= 2)
  • mdalevels: MDA grijstinten
  • slots: Opgeslagen instellingen voor deze bron
  • save / load / clear: Instellingen slots in flash (8 per bron)
  • default [n|off]: Slot dat bij boot wordt toegepast
  • detect / measure: Welke bron auto-detect zou kiezen / meet de dot clock
  • tune [apply]: Meet de dot clock en bepaal de phase (auto tune)
  • osd ...: On-screen display; osd live schakelt live metingen in
  • ir on|off / ir map: Print IR remote codes / lijst geladen key map
  • capture / fastcap: Dump frame via USB
  • dvi_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: tune print het resultaat, tune apply past het toe.
  • Via de computer: tools/autotune.py doet hetzelfde via een fastcap dump.

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).