ASMtrad CPC

Apprenez l'assembleur Z80

Synchronisation avec le moniteur

Le CPC a une particularité dans le monde des micro-ordinateurs (c'est le nom qu'on leur donnait à l'époque)

Le CPC était vendu avec un moniteur

Ce fait exceptionnel dans l'informatique de l'époque signifie simplement pour nous que le moniteur fait partie entière du CPC.
Un CPC branché sur autre chose que son moniteur d'origine n'est donc plus un CPC puisqu'il n'est plus complet.
Son rendu est altéré et n'est plus fidèle à celui d'origine.
Je ne parle même pas des CPC branchés sur des écrans LCD et autres donc le rafraichissement de l'image n'a rien à voir avec celui d'un écran CPC.

Dans ce chapitre nous allons parler de synchronisation avec ce même moniteur afin d'afficher une image correctement.

Nous allons tout d'abord introduire la notion de temps machine, puis de fréquence de balayage, et enfin, de synchronisation.

Des notions importantes pour comprendre ce que l'on voit et ce que l'on doit faire.

Le temps machine:

Le temps machine correspond au temps pris par les instructions par le Z80.

Chaque instruction prend un certain temps à être prise en compte et à agir.

L'instruction la plus rapide est l'instruction NOP.
Le NOP ca ne sert pas à grand chose sinon à attendre 1µs
On prendra donc cette instruction comme référence.
Aussi on donnera le temps pris par les autres instructions en donnant le nombre de NOPs qu'elles prennent.

(j'en profite pour faire un petit écart et signaler que sur spectrum on comptera plutôt les cycles T)

Par exemple prenons le LD HL,valeur. Eh bien cette instruction prend 3 NOPs (donc 3µs)
Pareil pour LD DE,val ou LD BC,val: 3 NOPs
Le LDIR quand à lui en prend 6 quand BC>0 et 5 quand BC=0.

Calculons donc le nombre de NOPs pris par:

                                LD         HL,#C001               ;3 NOPs
                                LD         DE,#C000               ;3 NOPs
                                LD         BC,#4F                 ;3 NOPS
                                LDIR                              ;6*#4e + 5 = 473 NOPs

On voit tout de suite que le LDIR consomme beaucoup de CPU.

Mais si je parle de CPU et de temps machine c'est bel et bien parce qu'il y a une limite.

50Hz

50 Hz c'est la fréquence de l'écran d'un CPC.
50Hz cela signifie qu'il y a 50 images par secondes.

Notre limite c'est justement celle du temps pris par l'affichage d'une image.

Une ligne prend 64 NOPs.
Nous avons 312 lignes par ecran.
Nous avons donc 64*312 NOPs par écran, soit 19968 NOPs par écran.

Si on reprend notre routine de scroll, nous avons 16*473 NOPs pour faire les 16 lignes. Soit 7568 NOPs de pris.
On peut en déduire que le temps d'un écran notre routine a le temps de s'executer: 19968/7568=2.63 fois...
Hors justement si vous réfléchissez, vous vous rendrez compte que vous ne verrez pas 1 décalage mais 2.63 de votre scroll le temps que le prochain écran soit affiché par le moniteur...

Et c'est pour cela que c'est rapide !!!

Heureusement pour nous il y a une solution...

Synchronisation avec le moniteur

Le moniteur c'est l'objet: le gros machin qui siffle et sur lequel vous regardez.
L'écran c'est ce que le CPC génère et envois au moniteur !!!

Vous pouvez jeter le moniteur le long d'un mur (c'est un exemple hein ^^), pas l'écran ...

Notre moniteur a besoin de savoir quand un nouvel écran commence. Pour cela il repère deux signaux: la VBL et la HBL.

La VBL sert au moniteur pour se caler verticalement. Pour le moniteur, quand le signal VBL est détecté, il commence l'affichage de l'image.

Vous pouvez d'ailleurs voir cette VBL en déréglant votre écran. Tournez l'espèce de vis derrière le moniteur, vous verrez une barre noire: c'est la VBL.
Sauf si votre moniteur est mal réglé, la VBL est donc toujours en haut de l'écran.

La HBL c'est la même chose mais pour le centrage horizontal du moniteur. Pour l'instant on ne s'y interessera pas.

Revenons à notre VBL:

Vu que le moniteur se cale dessus, on en conclu donc que lorsqu'il y a VBL, nous sommes donc en haut du moniteur.

Voyons donc comment le moniteur se cale et affiche une image:

Balayage ecran

Les flèches dans l'image correspondent au canon à électron qui envoi nos joyeux pixels.

Le Moniteur se cale sur la VBL. On se retrouve donc en haut de l'écran.
La HBL lui permet de se caler horizontalement on est donc alors en haut à gauche.

Le moniteur affiche ensuite chaque ligne en partant de la gauche et affiche vers la droite.
Quand un nouveau signal HBL est envoyé, la ligne est terminée pour lui et il descend donc d'une ligne et retourne à gauche, puis continue d'afficher.

Arrivé tout en bas, un nouveau signal VBL est détecté. L'écran est terminé et le canon à électron retourne en haut à gauche.

Nous avons donc le temps entre 2 VBL pour notre code afin de rester à 50Hz.
Si nous dépassons cet écart, alors nous ne serons plus synchronisé et on se mangera le balayage (vous avez déjà du voir cela, des sprites coupés qui sont décalés).

Détecter la VBL

Nous avons de la chance, contrairement à d'autres machines inférieures (il me semble que c'est le cas de l'Oric), nous pouvons nous synchroniser avec le moniteur en détectant le signal VBL. (OUF).

Le signal VBL c'est le CRTC qui l'envoie. Mais nous ne pouvons pas passer par lui pour le détecter...

Heureusement pour nous, lorsqu'une VBL est en court (car le signale dure un certain temps), 1 bit est mis à 1 dans le port B du PPI.

Ne cherchez pas à comprendre pour le moment comment ça marche, nous y reviendront plus tard.

Voyons juste le fameux port B du PPI:

ppi port B

Bon la c'est clair, pour le moment la plupart des bits n'ont aucun interet pour nous et seul le bit 0 nous intéresse.

Mais comment lire un port ?

Avec l'instruction IN A,(C)
Vous placez dans B l'adresse du port en premier.
Vous faites votre IN A,(C)
Vous aurez dans A le contenu du port.

Reste à lire le bit 0.

Pour cela nous allons nous servir du flag Carry que vous connaissez déjà.
Afin de récupérer notre bit 0, nous allons faire une rotation du contenu de A avec récupération du bit dans le flag Carry.

Pour cela nous utilisons l'instruction RRA qui signifie: Rotation Right(vers la droite donc) de A.

Voyons comment cela fonctionne:

RRA instruction

Comme on peut le voir, à chaque RRA, les bits scrollent bit à bit et le 0 va dans la carry. Ce qui nous arrange bien.

Pour tester la VBL nous pouvons donc faire:

                                LD         B,#F5                  ;adresse du port B du PPI
                FRAME           IN         A,(C)                  ;On récupère l'octet contenu sur le port dans A
                                RRA                               ;On fait une rotation afin de récupérer le bit 0 dans le flag carry
                                JR         NC,FRM                 ;tant que le flag carry n'est pas à 1 on boucle au label frm

Vous n'avez plus qu'à ajouter ceci dans vote routine de scroll au début:

Debut
test VBL
Scroll
JP Debut

Votre scrolling n'aura maintenant lieu qu'une fois par image affichée. Par extension on dit souvent: "une fois par VBL"