Bref, j'ai fait la partie "Ports" du tuto. Si vous pensez que j'ai oublié quelque chose n'hésitez pas à me le signaler. Je n'ai pas parlé en détail de l'utilisation de l'écran, je pense que ce serait mieux de consacrer un chapitre au double-buffering et au mode 8bits avec tout ce que ça implique (palette, etc...).
(il peut y avoir des petite fautes même si normalement j'ai vérifié, j'étais un peu fatigué quand je l'ai rédigé).
Voilou, deux heures toute de même.
Les ports
Les ports sont très importants en assembleur : ils permettent entre autre, de gérer la pression des touches sur le clavier, configurer l'écran, communiquer par USB avec une autre calculatrice... c'est une notion incontournable de l'assembleur ! Ces derniers servent donc à faire le lien entre les composants de la calculatrice et le programmeur. Concrètement, on va, par exemple, pouvoir dire à l'horloge de la calculatrice de changer l'heure, à l'écran de s'éteindre, au port USB d'envoyer quelque chose... tout cela grâce aux ports !
Cependant, un élément va compliquer leur utilisation sur les calculatrice eZ80. En effet, les ports des calculatrices eZ80 sont dits "memory-mapped". Pour faire court, sur les calculatrices Z80 (Ti-83+/Ti-84+...), les ports étaient accessibles directement et normalement grâce aux instructions
IN a,(port)
pour récupérer la valeur d'un port, et OUT (port),a
pour la modifier. Néanmoins, sur Ti-83 Premium CE l'utilisation des instructions IN et OUT est prohibée et tenter des les utiliser ne causera soit rien, soit un RAM CLEARED. Ces restrictions sont supposées protéger et donner un sens au mode examen qui aurait pu être facilement reproduit et contourné dans le cas où un programme avait pu utiliser le port de la LED du mode examen afin d'en imiter le fonctionnement.Heureusement, il existe quand même une solution pour accéder aux ports que nous permet d'utiliser Texas Instrument. En effet, certains ports sont "mappés en mémoire" c'est-à-dire qu'ils vont pouvoir être modifiés seulement en modifiant une adresse mémoire. C'est le cas notamment pour le clavier, l'écran, les timers, l'USB... mais bien entendu pas la LED du mode examen !
Les ports sont mappés à partir de l'adresse mémoire $E00000. Par exemple, le port du clavier est mappé en mémoire à partir de l'adresse $F50000. Afin de connaître tous les ports qui peuvent être utilisés, je vous conseille de suivre ce lien vers le wikiti. Vous y trouverez tous les ports qui ont été découverts jusqu'à maintenant. Pour savoir si un port est "memory-mapped", il suffit de voir si le champ "Memory-mapped address:" existe en haut de la page décrivant le port, dans la section "Synopsis".
Afin de mieux comprendre comment cela fonctionne, nous allons aborder un exemple simple, récupérer les minutes de l'heure actuelle :
- Code: Select all
ld hl,($F30004) ; On récupère les minutes.
call _dispHL ; On affiche HL qui contient le nombre de secondes
Expliquons un petit peu. Nous voyons à cette adresse que le port "Real-Time Clock" est le port numéro $8000 et est mappé à l'adresse $F30000 en mémoire. De plus, les minutes sont stockées du port $8004 à $8007 (toutefois les minutes n'allant que de 0 à 59, seulement un octet sera utilisé sur les quatre dédiés aux minutes). L'adresse à récupérer est donc $F30004. Ensuite, on affiche les minutes avec la fonction système _dispHL qui, comme son nom le laisse présager, affiche la valeur du registre HL à l'écran.
Nous allons, en dernier lieu et partiellement, voir l'utilisation des ports les plus importants, c'est-à-dire le port du clavier et de l'écran.
Utilisation du clavier
Le clavier a une utilisation spéciale et un peu plus complexe malgré sa fréquente utilisation dans les programmes. Il nécessite quelques connaissances.
Le port du clavier a pour numéro $A000 et est mappé à l'adresse $F50000. Avant de détecter la pression des touches, nous avons besoin d'initialiser le clavier. Pour cela nous allons devoir d'abord choisir un mode pour la clavier. Il en existe quatre mais seulement trois peuvent éventuellement nous intéresser :
- Le mode "repos" : le clavier ne fait rien et ne scanne rien
- Le mode "unique scan" : le clavier est scanné une fois, puis il revient au mode "repos"
- Le mode "scan continu" : le clavier est scanné encore et encore indéfiniment...
- Code: Select all
di ; On désactive les interruptions (obligatoire)
ld hl,$F50000
ld (hl),2 ; On met le clavier en mode "un seul scan"
xor a,a
scan_wait:
cp a,(hl) ; On attend que le clavier soit retourné en mode repos ce qui voudra dire que la détection des touches est terminée
jr nz,scan_wait
; Quand la détection est terminée, on peut commencer à lire les ports
ld a,($F50012)
cp a,32 ; si la touche 2NDE a été pressée...
call z,routine
ei ; On peut réactiver les interruptions
Ici, nous avons pris l'exemple de la touche 2NDE dont l'état (enfoncée ou non) se situe à l'adresse $F50012 sur le bit 5. Pour connaître la correspondance des touches, je vous conseille de jeter un œil au tableau sur cette page. Comme on peut le voir on fait une pause (scan_wait) avant de lire le clavier, sans elle la lecture serait erronée donc ne l'oubliez pas !
Utilisation de l'écran
Le port de l'écran nécessite un chapitre entier mais nous allons aborder brièvement les bases de son utilisation. L'écran est par défaut en 16bits, c'est à dire qu'il y a 2^16=65536 couleurs disponibles par pixel. Chaque pixel possède une nuance de rouge, de vert et de bleu, les trois couleurs primaires en informatique. Par défaut (et je dis par défaut car il est possible de mettre l'écran en mode 8bits) chaque pixels possède donc 16 bits. Les cinq premiers bits codent pour le rouge, les six suivants pour le vert, et enfin les cinq derniers pour le bleu. On remarque que nous avons :
%0011001110010110
Maintenant, l'objectif est de savoir comment modifier la valeur d'un pixel à l'écran. Notre Ti-83 Premium CE possède une vRam autrement dit une Vidéo RAM qui est un espace mémoire destiné à faire l'intermédiaire entre la mémoire et l'écran. Grosso modo, il suffit tout simplement de modifier la vRam pour que les pixels changent instantanément de couleur sur l'écran.
Nous savons que l'écran fait 320*240 pixels, avec 16 bits par pixel (=2 octets). La vRam fait donc logiquement 320*240*2, soit 153,6Ko, ce qui est énorme quand on sait que la RAM disponible à l'utilisateur fait autant !
La vRam est située à partir de l'adresse $D40000 sur 153600 octets. Prenons un exemple tout simple, on veut changer le 187ème pixel pour qu'il affiche du rose :
- Code: Select all
ld hl,%1111100000010000
ld (vRam+(186*2)),hl
À noter que comme le registre HL fait 24 bits, les 16 bits du pixel 187 seront bien modifiés, toutefois la moitié du pixel suivant (8 bits), le 188, sera mise à 0.
Il est alors possible de modifier une grand partie de l'écran grâce à un LDIR, et avec un peu de réflexion, d'afficher des sprites et des images à l'écran.
En rappel, n'oubliez pas d'aller voir le wikiti pour connaître tous les ports et leur adresse !
Voir la liste des ports connus à ce jour.