Computer / Programmazione / Z80 · 12 aprile 2019 5

LM80C: TMS9918A

In questo articolo mi piacerebbe illustrare alcuni dei problemi che ho incontrato usando il TMS9918A e come li ho risolti.

Ma cominciamo dagli inizi. Nel 1979 Texas Instruments commercializzò il TMS9918 (chiamato VDP, da “Video Display Processor”), un chip video che più tardi venne usato nell’home computer TI99/4: questo chip era capace di generare testo e grafica ad una risoluzione di 256×192 pixel. Inoltre, era capace di generare gli sprite, ossia oggetti mobili che sono indipendenti dallo sfondo sottostante e che possono essere mossi in giro per lo schermo direttamente dal chip video. Il TMS9918 fu in seguito sostituito dal TMS9918A, sviluppato per il TI99/4A.

TMS9918A

TMS9918A

Il TMS9918 aveva un limite: non supportava la grafica bitmap. Questo significava che non poteva manipolare i singoli pixel sullo schermo. Poteva solo manipolare la grafica a tessere (tile): l’immagine era divisa in tessera, ognuna delle quali era grande 8×8 pixel. Ma le tessere erano solo 256 mentre l’immagine era alta (256/8=) 32 tessere e larga (192/8=) 24 tessere, per un totale di 32×24=768 tessere. E’ facile vedere che un completo set di tessere non poteva coprire l’intera immagine. Questa fu la motivazione che spinse Texas Instruments a risolvere questo limite rilasciando il TMS9918A: la “A” stava ad indicare una versione avanzata con una nuova modalità grafica dove lo schermo era diviso in 3 aree di 256 tessere ciascuna, per un totale di 768 tessere, così che ogni cella video di 8×8 pixel avesse la sua tessera. Così facendo il VDP aveva la capacità di indirizzare direttamente ogni singolo pixel dell’immagine, permettendo una vera grafica bitmap. Il TMS9918A fu usato nel TI99/4A di Texas Instruments ed in una larga varierà di sistemi come i computer MSX e diverse console da gioco di Sega. A differenza del MOS VIC-II di Commodore, che fu usato solo nei computer Commodore 64, Texas Instruments vendette il VDP ad un sacco di produttore così che alla fine divenne uno dei chip video più diffusi di quel tempo. Oggigiorno può essere trovato online per pochi euro: per questa ragione ho deciso di usarlo nel mio piccolo computer.

Il VDP può essere interfacciato con un processore con soli un bus dati ad 8 bit e 3 linee di controllo, niente di più niente di meno. Un’altra caratteristica è l’uso di una VRAM dedicata, che è al di fuori dello spazio di indirizzamento della CPU: questo significa che il VDP non toglie memoria alla RAM di sistema. Il risvolto negativo è che la CPU può accedere alla VRAM solo attraverso il VDP. Il TMS9918A è stato seguito dal TMS9928A e dal TMS9929A: il “28” era in pratica lo stesso chip ma invece di un’uscita composita generava un segnale a componenti di tipo YPbPr (fatto dalla luminanza e dalle differenze di colore) mentre il “29” era il “28” con il supporto PAL (il “18” ed il “28” erano in standard NTSC). Potreste chiedermi perché ho scelto il TMS9918A se vivo in un’area PAL… beh, il TMS9929A non può essere connesso direttamente ad una TV perché non genera proprio un segnale YPbPr ma Y/R-Y/B-Y: il segnale è composto dalla luminosità (Y) con le differenze di colore con il rosso (R-Y) e con il blu (B-Y). Questo significa che se cercassi di connettere l’uscita del TMS9929A all’ingresso YPbPr della mia TV l’unica cosa che potrei vedere sarebbe un’immagine in bianco e nero: necessiterei di un adattatore da Y/R-Y/B-Y a YPbPr. Invece, il TMS9918A può essere connesso direttamente ad una TV senza bisogno di nessuna interfaccia: la “magia” è fatta grazie al fatto che quasi tutte le TV moderno supportano sia lo standard NTSC che PAL.

Dopo questa introduzione al VDP, vorrei parlarvi dei problemi che ho incontrato mentre cercavo di ottenere un’immagine decente dal mio computer. Il motivo era la… VRAM. Il VDP è stato progettato in un periodo durante il quanto le DRAM erano più economiche e più affidabili delle SRAM perciò gli ingegnere scelsero di integrare nel chip la circuiteria necessaria ad interfacciarsi con le prime. Le DRAM non sono più facili da gestire rispetto alle SRAM: esse necessitano di un livello di tensione negativo (-5 V) ed hanno un modo diverso di indirizzare le loro celle. Per fare un banco da 16 KB di VRAM servono 8 chip 16 Kx1: questi chip sono matrici di 16.384 singoli bit per cui per fare un singolo byte di dato il VDP deve leggere 1 bit da ognuno degli 8 chip. Inoltre, a differenza delle SRAM, le DRAM usano un sistema di indirizzamento basato su righe e colonne: in genere, per recuperare un dato da una SRAM si deve fornire l’indirizzo della cella sul bus di indirizzi della memoria. Invece, con le DRAM bisogna prima di tutto inviare l’indirizzo della riga, poi impostare la linea elettrica delle righe, poi indicare l’indirizzo della colonna, e poi impostare la linea della colonna: solo dopo che questa sequenza è stata completata il chip restituirà il contenuto della cella selezionata. Troppo noioso… Ho perciò guardato in giro alla ricerca di una soluzione… e l’ho trovata. Ho trovato un documento di Tom LeMense datato 2010 che sembrava offrire una soluzione moderna a questo problema: egli descriveva un modo per interfacciare il chip SRAM al VDP usando alcuni latch per assemblare gli indirizzi della riga e della colonna e comporre l’indirizzo completo. Lo schema, che potete trovare in PDF nel mio repository GitHub, lezione 11, non ha funzionato, almeno per me. Non so perché: semplicemente, ottenevo sullo schermo la spazzatura che ho fatto vedere nei miei precedenti test. Ho guardato ancora sul web e sembrava che funzionasse a tutti quelli che usavano quello schema… Alla fine, ho trovato un altro modo di collegare il VDP ai latch e poi alla SRAM, e questo ha funzionato perfettamente! Questo schema è stato disegnato da J.B.Langston per la sua scheda grafica basata sul VDP che ha progettato per il computer RC2014. Come potete vedere qui sotto, non ha seguito la sequenza numerica per collegare le uscite dei latch agli ingressi della SRAM (area gialla a destra):

TMS9918A & SRAM

TMS9918A e SRAM

Dato che il VDP può indirizzare solo 16 KB di VRAM, sono usate solo 14 linee, divise in 2 gruppi: 7 bit per la riga e 7 per la colonna, rispettivamente. Il circuito memorizza l’indirizzo della riga nel primo latch, poi l’indirizzo della colonna nel secondo latch: alla fine i bit sono presentati sui pin di output per comporre l’indirizzo completo da inviare alla SRAM. Dopo di ciò il dato può essere letto sui pin RD7..0 direttamente dalla SRAM o scritti su di essa attraverso un terzo latch (dato che il VDP fa uscire i dati sulle stesse linee AD7..0).

Non so perché e non so come egli Langston ha trovato che doveva cambiare la sequenza dei collegamenti dell’indirizzo ma so per certo che questa cosa funziona. Il mio computer adesso mostra il suo bel nome nell’angolo in alto a sinistra dello schermo:

LM80C-welcome message

LM80C: messaggio di benvenuto

Ecco alcune cose da tenere a mente:

  • seguite i collegamenti tra i latch e l’SRAM;
  • non dimenticate che il VDP, come gli altri processori di TI di allora, considera il bit n°7 come il LSB ed il bit n°0 come il MSB, per cui dovete invertire i pin del bus dati: collegare da D0..D7 a D7..D0;
  • visto che il dato su RD7..RD0 deve essere stabile prima che la linea della colonna sia tirata su, l’autore originale usa 3 sezioni di un NOT in cascata per ottenere il ritardo;
  • è fondamentale che ci sia un collegamento fra i pin RDx del VDP, i pin IOx della SRAM ed i pin ADx: controllate perciò che ogni pin sia connesso al corrispondente numero nella catena (ad esempio AD0 è connesso al VDP attraverso la linea che passa per il terzo latch tra 1D e 1Q);
  • non mescolate chip LSxx con quelli HCTxx: dato che i tempi sono fondamentali, usate integrati della stessa famiglia;
  • un altro punto CRITICO è la frequenza del segnale di clock: il cristallo deve essere a 10,738635 MHz, con una tolleranza molto bassa (+/-0,005%). Non è molto comune ma si riesce a recuperare se cercate un po’. La frequenza è importante: è usata per generare il clock interno che serve al VDP per operare, incluso il clock di 3,579545 MHz usato per generare il segnale del color, il segnale che porta le informazioni del colore nel segnale video. Un’altra cosa da tenere in considerazione sono i condensatori: un valore di 33 pF dovrebbe essere buono per ogni tipo di circuito (la scheda tecnica suggerisce un valore compreso fra 15 e 39 pF, a seconda della capacità parassita del circuito).

Come al solito lo schema ed il codice sono sul mio repository Github.