# Les cartes graphiques/Le Video Display Controler

Dans les années 70-80, un système vidéo pouvait être fabriqué de deux grandes manières différentes. La première concevait la carte d'affichage à partir de composants très simples, comme des portes logiques ou des transistors, à partir de zéro, sans réutiliser de matériel existant. De telles cartes vidéos avaient des performances et des fonctionnalités très variables, mais étaient très complexes à concevoir et coutaient cher. La seconde catégorie utilisait des Video Display Controler (VDC), des circuits déjà tout près, placés dans un boitier, produits en masse, qu'il suffisait de compléter avec une mémoire vidéo et quelques autres circuits pour obtenir un système vidéo. De tels circuits permettaient d'obtenir des performances décentes, voire très bonnes, pour un prix nettement inférieur. Les deux fonctionnent de la même manière, peu importe qu'il s'agisse d'un VDC ou d'un circuit fait main. Les deux contiennent globalement les mêmes circuits, ils fonctionnent de la même manière.
Dans le chapitre sur les cartes d'affichage, nous avons vu qu'une carte d'affichage contient trois à quatre circuits distincts : un framebuffer, un circuit de contrôle, le circuit d’interfaçage électrique avec l'écran (le RAMDAC) et éventuellement une connexion avec le bus. Le VDC correspond au circuit de contrôle. Les fonctionnalités d'un VDC sont très variables. Ils s'occupent des choses de base, comme gérer la résolution, l'envoi de l'image à afficher à l'écran, ce genre de choses. Il ne s'occupe pas de la transmission avec le bus, il ne gère pas vraiment l’interfaçage électrique.
Si la plupart des VDC communiquent avec la mémoire vidéo, il existe quelques exceptions qui se débrouillent sans mémoire vidéo ! C'est le cas des Video shifters dont nous parlerons plus tard. Les Video shifters sont vraiment à part des autres VDP, leur design basé sur l'absence de mémoire vidéo est responsable de différences vraiment profondes comparé aux autres VDP, ce qui fait qu'ils auront droit à leur propre section à la fin du chapitre.
La meilleure manière d'aborder les VDC est de d'abord les voir comme des espèces de boite noire, dont on ne se préoccupe pas du contenu en premier lieu. Un VDC communique avec l'écran, le processeur, et éventuellement avec la mémoire vidéo. Dans ce chapitre, nous allons voir comment il communique avec l'écran, puis voyons l'interface avec le processeur. C'est dans le chapitre suivant que nous allons voir ce qu'il y a à l'intérieur. La raison à cela est que plusieurs signaux de commandes émis par le VDC, certains à destination du processeur et d'autres à destination de l'écran, sont générés par les mêmes circuits.

## L'interface du VDC avec l'écran

Un écran est considéré par la carte graphique comme un tableau de pixels, organisé en lignes et en colonnes. Les écrans LCD sont bel et bien conçus comme cela, c'est plus compliqué sur les écrans CRT, mais cela ne change rien du point de vue de la carte graphique. Chaque pixel est localisé sur l'écran par deux coordonnées : sa position en largeur et en hauteur. Par convention, on suppose que le pixel de coordonnées (0,0) est celui situé tout haut et tout à gauche de l'écran. Le pixel de coordonnées (X,Y) est situé sur la X-ème colonne et la Y-ème ligne. Le tout est illustré ci-contre.

### Le balayage progressif et l'entrelacement

L'écran peut afficher une image en utilisant deux modes principaux : le balayage progressif, et le balayage entrelacé.
Avec le balayage progressif, la carte graphique doit envoyer les pixels ligne par ligne, colonne par colonne : de haut en bas et de gauche à droite. Le balayage progressif est utilisé sur tous les écrans LCD moderne, mais il était plus adapté aux écrans CRT. Sur les écrans plats, l'image est transmise à l'écran, mais est affichée une fois qu'elle est intégralement reçue, d'un seul coup. Mais sur les anciens écrans de télévision, les choses étaient différentes.
Les vieux écrans CRT fonctionnaient sur ce principe : un canon à électrons balayait l'écran en commençant en haut à gauche, et balayait l'écran ligne par ligne. Ce scan progressif de l'image faisait apparaître l'image progressivement et profitait de la persistance rétinienne pour former une image fixe. L'image était donc affichée en même temps qu'elle était envoyée et le scan progressif correspondait à l'ordre d'allumage des pixels à l'écran.
La technique du balayage progressif n'avait pas de défauts particuliers, ce qui fait que tous les écrans d’ordinateurs CRT l'utilisait. Mais les télévisions de l'époque utilisaient une méthode différente, appelée l'entrelacement. Avec elle, l'écran faisait un scan pour les lignes paires, suivi par un scan pour les lignes impaires. Le tout est illustré dans l'animation ci-contre.
L'entrelacement donne l'illusion de doubler la fréquence d'affichage, ce qui est très utile sur les écrans à faible fréquence de rafraîchissement. Pour comprendre pourquoi, il faut comparer ce qui se passe entre un écran à scan progressif non-entrelacé et un écran entrelacé. Avec l'écran non-entrelacé, l'image met un certain temps à s'afficher, qui correspond au temps que met le canon à électron à balayer la totalité de l'écran, ligne par ligne. Avec l'entrelacement, le temps mis pour balayer l'écran est le même, car le nombre de lignes à balayer reste le même, seul l'ordre change.
Sur l'écran entrelacé, l'image s'affiche à moitié une première fois (sur les lignes paires) avant que l'image complète s'affiche. La moitié d'image affichée par l'écran entrelacé a une résolution suffisante pour que le cerveau humain soit trompé et perçoive une image presque complète. En clair, le cerveau verra deux images par balayage complet : une image partielle lors du balayage des lignes paires et une image complète lors du balayage des lignes impaires. Sans entrelacement, le cerveau ne verra qu'une seule image lors de chaque balayage complet.
L'effet est d'autant plus important que la résolution verticale (le nombre de lignes) est important. De plus, l'effet est encore plus important si l'ordinateur calcule un grand nombre d'images par secondes. Par exemple, pour un écran avec une fréquence de rafraîchissement de 60 Hz et un jeu vidéo qui tourne deux fois plus vite (à 120 images par secondes, donc), l'image sur les lignes impaires sera plus récente que celle sur les lignes paires. Le cerveau humain sera sensible à cela et verra une image plus fluide (bien qu'imparfaitement fluide).
Le nombre de lignes est toujours impair (normes analogiques : 625 en Europe, 525 en Amérique), ce qui fait un nombre non entier de lignes pour chacune des 2 trames (impaires et paires). Par exemple, pour 625 lignes cela fait 312,5 lignes par trame. Le balayage vertical étant progressif durant le balayage horizontal, les lignes sont imperceptiblement penchées. À la fin du balayage d'une trame, le rayon se retrouve au milieu de la ligne horizontale, soit un décalage vertical d'une demie-ligne (voir image ci-dessous).

### La fréquence de rafraichissement

Même si cela commence à changer de nos jours, l'écran affiche un certain nombre d'images par secondes, le nombre en question étant désigné sous le terme de fréquence de rafraîchissement. Pour un écran avec une fréquence de rafraîchissement de 60 Hz (60 images par secondes), la carte graphique doit envoyer une nouvelle image tous les (1 seconde / 60) = 16,666... millisecondes. Sur les écrans LCD, la fréquence de rafraîchissement ne dépend pas de la résolution utilisée, en raison de différences de technologie. Sur les anciens écrans CRT, la fréquence de rafraîchissement dépendait de la résolution utilisée, et la carte d'affichage devait alors gérer le couple résolution-fréquence elle-même et la gestion de la fréquence de rafraîchissement était donc plus compliquée.

### La gestion des timings pour la communication avec l'écran

Le câble qui relie la carte graphique à l'écran transmet au mieux un seul pixel à la fois, voire un seul bit à la fois. On ne peut pas envoyer l'image d'un seul coup à l'écran, et on doit l'envoyer pixel par pixel. L'écran traite alors ce flux de pixels de deux manières différentes. Dans le cas des écrans LCD, le plus intuitif, l'écran accumule les pixels reçus dans une mémoire tampon et affiche l'image une fois qu'elle est totalement reçue. Pour les écrans CRT, l'écran affiche les pixels reçus immédiatement dès leur réception sur l'entrée. Dans les deux cas, il faut envoyer les pixels dans un certain ordre bien précis.
Un point important est que la carte graphique ne peut pas envoyer un flux de pixels n'importe quand et doit respecter des timings bien précis. Le flux de pixel envoyé à l'écran est souvent structuré d'une certaine manière, avec des temps de pause, un temps de maintien minimum pour chaque pixel, etc.
Déjà, il faut tenir compte des timings liés à la transmission de l'image elle-même. La carte graphique doit envoyer les pixels avec des timings tout aussi stricts, qui dépendent du standard vidéo utilisé. Chaque pixel doit être maintenu durant un certain temps bien précis, il y a un certain temps entre la transmission de deux pixels, etc. Et le circuit d’interfaçage doit gérer le temps de transmission d'un pixel. Pour cela, le VDC envoie un signal d'horloge dont la période correspond au temps de transmission/affichage d'un pixel. En, clair, le VDC envoie un pixel à chaque cycle d'horloge.
Ensuite, il faut prévenir l'écran qu'on a fini de transmettre une image avec un signal de synchronisation verticale, qui indiquait à l'écran qu'une image entière vient d'être transmise. Le VDC transmet l'image pixel par pixel, et lève ce signal de synchronisation verticale une fois l'image intégralement transmise. Ce signal était transmis sur un fil spécialisé, qu'on trouve sur la plupart des connecteurs VGA. De nos jours, sur les standards HDMI, DisplayPort, et autres, les choses sont plus compliquées, mais ce signal est quand même transmis, bien que pas forcément sur un fil spécialisé.
Enfin, il faut aussi tenir compte d'autres timings pour gérer la résolution. Les pixels sont envoyés ligne par ligne, mais une ligne de pixel n'a pas la même taille suivant la résolution : 640 pixels pour du 640 × 480, 1280 pour du 1280 × 1024, etc. La carte graphique doit donc indiquer quand commencent et se terminent chaque ligne dans le flux de pixels. Sans cela, on ne pourrait pas gérer des résolutions différentes. Pour cela, le VDC envoie un signal de synchronisation horizontale une fois qu'il a fini d'envoyer une ligne.
En tout, cela fait au minimum trois signaux : une horloge pour la transmission des pixels, un signal de synchronisation verticale, et un signal de synchronisation horizontale. Sans cela, impossible d'envoyer des pixels à l'écran ou de gérer la résolution convenablement. Et il y a d'autres contraintes de timings dont nous parlerons plus bas, qui ne sont pas évidentes pour le moment. Par exemple, sur les écrans CRT, il y a un temps de latence à la fin d'une ligne pour que le canon à électron se déplace sur le début de la ligne suivante. Et cela impose de ne pas démarrer l'envoie de la ligne suivante avant un certain temps. Cela il n'existe plus sur les écrans LCD, mais il fallait le prendre en compte à l'époque.

### L'exemple du standard VGA

Un bon exemple est le standard VGA, qui était le seul utilisé pour connecter les écrans CRT, mais qui est encore utilisé de nos jours sur les écrans LCD. Avec ce standard, le connecteur contenait trois fils R, G, et B pour envoyer la couleur, codée en analogique. Il existait un fil H-SYNC pour indiquer qu'on transmettait une nouvelle ligne et un fil V-SYNC pour indiquer qu'on envoie une nouvelle image. Une nouvelle ligne ou image est indiquée en mettant un 0 sur le fil adéquat. Jusque là, rien de surprenant, c'est une redite de ce qu'on a dit plus haut. On trouve aussi plusieurs fils pour la masse, à savoir le 0 Volt, ainsi qu'une tension d'alimentation. Il y a une masse générale, ainsi que plusieurs masses, une par signal RGB.
Et enfin, il faut citer la connexion DDE/DDC qui permet de communiquer des informations de configuration à l'écran. Quand vous branchez l'écran à une carte graphique, celle-ci communique avec l'écran pour savoir quelles sont les résolutions supportées, quelle fréquence de rafraichissement est supporté, si l'écran supporte des couleurs 32 bits, etc. Sans cela, impossible de configurer la résolution. Pour cela, l'écran contient une petite mémoire ROM, dont le contenu est standardisé, qui contient toutes les informations nécessaires pour configurer l'écran.LA carte graphique lit cette ROM en passant par un bus appelé le bus Display Data Channel, qui permet à la carte graphique de lire cette ROM, d'interroger l'écran sur les résolutions et fonctionnalités supportées. Le bus est un dérivé du bus I²c, et a trois fils dédiés : un pour l'horloge, l'autre pour la transmission des données, et une masse dédiée.
Les premières subtilités du standard VGA viennent des timings des signaux HSYCN et VSYNC. Le signal HSYNC n'est pas envoyé dès la fin de la ligne : il y a un temps d'attente de quelques microsecondes entre la fin de la ligne et l'envoie du signal HSYNC. Le signal HSYNC est maintenu durant quelques microsecondes, la durée d'envoi est fixe. Puis, on a encore un nouveau temps d'attente avant l'envoi de la prochaine ligne, durant lequel le signal HSYNC n'est pas envoyé. Durant ces trois périodes (deux temps d'attentes, envoi de HSYNC), aucun pixel n'est envoyé à l'écran.
Et il y a la même chose avec les signaux VSYNC, même si les timings sont différents. On devait attendre un certain temps entre la transmission de deux lignes, ce qui introduisait des vides dans le flux de pixels. Même chose entre deux images, sauf que le temps d'attente était plus long que le temps d'attente entre deux lignes. Le tout est détaillé dans le schéma ci-dessous, qui détaille le cas pour une résolution de 640 par 480.

## L'interface du VDC du point de vue du processeur

Pour le processeur, le VDC a une interface similaire à celle de n'importe quel périphérique : un paquet de registres, et éventuellement des mémoires SRAM intégrées. La mémoire vidéo peut être intégrée dans le VDP ou être séparée, les deux sont possibles.

### Les registres de configuration du VDC

La programmation d'un VDC se fait par en configurant des registres de configuration interne, qui permettent de configurer la résolution, la fréquence d’affichage, la position du curseur de souris, etc. Le processeur a juste à écrire dans ces registres, pour configurer la carte d'affichage comme souhaité.
En général, les registres de configuration sont accessibles directement par le processeur. Quelques adresses mémoire sont détournées et ne servent pas à adresser la mémoire, mais correspondent aux registres de configuration. Ce n'est ni plus ni moins que la technique des entrée-sorties mappées en mémoire que vous connaissez sans doute si vous avez déjà lu un cours d'architecture des ordinateurs. Il y a typiquement une adresse mémoire par registre, le processeur a juste à écrire dans cette adresse pour configurer le registre.
Plus rarement, les registres ne sont pas mappés en mémoire directement, mais sont accessibles par le processeur via une adresse. Le processeur écrit à une adresse précise, associée à la carte graphique. La configuration d'un registre se fait en deux temps : il écrit le numéro du registre à configurer, puis la donnée à écrire. La carte graphique reçoit ces deux informations l'une après l'autre, et les utilise pour configurer le registre elle-même.

### Le registre de statut

Le VDC incorpore presque toujours un registre d'état, ou un registre de statut qui permet au processeur de connaitre l'état du VDC. Il permet de savoir si le VDC est libre, s'il est en train d'afficher une ligne, si une erreur a eu lieu et laquelle. Le processeur a juste à lire le registre en question, pour vérifier l'état de la carte graphique. Chaque bit du registre de statut a une interprétation fixée à l'avance et fournit une information précise.
Plusieurs bits du registre de statut sont réservés au traitement des erreurs. Si le VDC rencontre une erreur, il met une valeur bien précise dans ces bits, appelée le code d'erreur. Typiquement, la valeur 0 indique qu'il n'y a pas d'erreur, les autres valeurs précisent une erreur. Le code d'erreur dépend de l'erreur en question et du VDC, il n'y a pas de standard pour ça.
Sur les VDC qui n'utilisent pas de raster interrupt, le registre de statut permet de savoir si le VDC est en train d'afficher une ligne à l'écran. Pour cela, le registre de statut du VDC contient un bit qui précise que l'écran est en train d'afficher une ligne. Il est appelé le bit de blanking horizontal. En général, ce bit est à 0 quand le VDC est en train de transmettre une ligne à l'écran, à 1 quand la mémoire vidéo est libre. Notons que ce signal n'est pas équivalent au signal HSYNC. Pour reprendre l'exemple du standard VGA, il y a deux temps d'attente avant et après l'envoi du signal HSYNC, où l'écran n'envoie pas de données. Le signal HSYNC est alors à 0, alors que le bit de blanking est bien à 1.

### Les raster interrupts

Le VDC contient aussi une sortie dédiée aux interruptions, connectée à l'entrée d'interruption du CPU (directement ou par l'intermédiaire d'un contrôleur d'interruption).
Les signaux de raster interrupt ne sont pas identiques aux signaux de synchronisation verticale et horizontale, ni aux signaux de blanking, même s'ils se ressemblent. La différence est que les signaux de synchronisation verticale/horizontale ont des contraintes de timing différents. Par exemple, le standard VGA impose que ces deux signaux soient maintenus durant un certain temps à l'écran, alors que les raster interrupts sont remises à zéro dès que le processeur est a pris en compte.

### La gestion de la palette indicée

Les VDC les plus complexes prennent en charge la palette indicée eux-mêmes. ILs sont assez rares, mais ils existent. Pour cela, ils incorporent une petite mémoire SRAM, dans laquelle est stockée la palette, à savoir la table de correspondance entre numéro de la couleur, et la couleur elle-même. Quand on envoie le numéro de couleur sur l'entrée d'adresse de cette SRAM, la sortie de donnée fournit la couleur codée en RGB. Le Processeur peut remplir cette SRAM lui-même, ce qui lui permet de configurer la palette.
La SRAM est soit mappée en mémoire, soit accessible de manière indirecte par des commandes spécialisées.

## L'interface du VDC avec la mémoire vidéo

Afficher une image à l'écran demande de prendre l'image dans le framebuffer et de l'afficher à l'écran. L'interface écran demande qu'on envoie les pixels les uns après les autres. Pour cela, le VDC doit parcourir le framebuffer pour lire les pixels un par un, dans le bon ordre.
Les VDC les plus simples ne permettent pas de faire cela automatiquement. Le processeur doit accéder à la mémoire vidéo et générer les adresses lui-même ! Les VDC de ce type sont appelés des Video shifters. Ils fournissent des signaux de commande à l'écran, mais n’accèdent pas à la mémoire vidéo. D'autres VDC plus complexes sont capables de générer des adresses mémoire et accèdent directement à la mémoire vidéo, ils gèrent d'eux-mêmes le parcours du framebuffer.

### Les VDC avec gestion des accès mémoire

Si on omet les video shifters, les VDC sont capables de lire les pixels à envoyer à l'écran depuis la mémoire vidéo. Pour cela, ils génèrent l'adresse du pixel à lire, au rythme d'un pixel par cycle d'horloge. La génération d'adresse est assez simple, surtout si le framebuffer est coopératif. Il suffit de démarrer à une adresse bien précise, celle où commence le framebuffer, et parcourir la mémoire dans l'ordre, en passant à l'adresse suivante à chaque cycle. Un simple compteur fait l'affaire.
Un point important est que la mémoire vidéo est quasi-systématiquement une mémoire de type DRAM, similaire aux mémoires SDRAM ou DDR des PC actuels. Elles tendent à perdre leur contenu au bout d'un certain temps, ce qui fait qu'elles doivent être rafraichies régulièrement pour éviter cet effacement. Les VDP les plus complexe peuvent incorporer des circuits pour effectuer ce rafraichissement automatiquement. Mais d'autres VDC plus simples font sans et ajoutent des circuits de rafraichissement mémoire séparés du VDC.
Et outre le rafraichissement, l'accès à une mémoire DRAM est plus complexe que l'accès aux autres mémoires RAM. Les timings des accès mémoire sont complexes, sans compter que l'adresse doit être envoyée en deux fois. Pour cela, un circuit appelé le contrôleur mémoire est nécessaire pour communiquer avec une DRAM. Le contrôleur traduit les adresses mémoires et signaux de commandes en commandes compréhensibles par la mémoire DRAM. Notamment, il reçoit une adresse mémoire et l'envoie en deux fois. Le contrôleur mémoire peut être intégré au VDC, ou être un circuit séparé, tout dépend du VDC en question.

### Les Video shifters : des cartes d’affichage sans mémoire vidéo

Les VDP les plus simples n'ont pas vraiment de noms, vu que ce sont des circuits très simples, mais un terme possible serait celui de Video shifters. Ce nom trahit le fait qu'ils reçoivent des données pixel par pixel, et les transforment en un flux de bit, voire un flux analogique (ils intègrent alors un RAMDAC). Ils ne peuvent pas envoyer de commandes/adresses à la mémoire vidéo, ils ne parcourent pas le framebuffer et ne lisent pas les pixels à envoyer à l'écran dedans, c'est le processeur qui le fait à leur place. Leur avantage est qu'ils se passent de mémoire vidéo dédiée et d'utiliser une mémoire unique pour le processeur et le système vidéo.
Ils sont très rares, les seuls à avoir été utilisé sur un microordinateur sont le RCA CDP1861 du micro-ordinateur soviétique COSMAC VIP, et le système vidéo du Sinclair ZX-81 (bien qu'il soit fabriqué avec des portes logiques et non avec un VDP). Sur les consoles de jeu, on peut citer le Television Interface Adaptor de l'Atari 2600.
Pour résumer, voici les fonctions possibles de ces circuits :
* RAMDAC et transformation octet/pixel en flux de bits ;
* génération des signaux de commande pour l'écran ;
* génération des raster interrupts.
Prenons l'exemple du RCA CDP1861. Il générait les signaux HSYNC et VSYNC de synchronisation verticale et horizontale pour l'écran, et transformait un octet reçu en flux de bits envoyés à l'écran (monochrome). L'intérieur de ce circuit était très simple : un registre à décalage pour la transformation parallèle-série, des compteurs pour la ligne et la colonne, quelques circuits de contrôle associés.
Le RCA CDP1861 était relié au processeur et à la mémoire comme indiqué ci-dessous. Le rendu d'une image se faisait en utilisant les raster interrupt. Le RCA CDP1861 générait une interruption à chaque fin de ligne, grâce à un compteur de ligne interne. Le processeur affichait une image grâce à une routine d'interruption, aidé par un contrôleur DMA intégré dans le processeur. La routine d'interruption configurait le contrôleur DMA, qui s'occupait d'envoyer l'image au RCA CDP1861, octet par octet. Il y avait un signal de synchronisation entre RCA CDP1861 et processeur/DMA : un bit émis par le RCA CDP1861 à destination du processeur indiquait qu'il était prêt à recevoir un nouvel octet.