π
<-
Chat plein-écran
[^]

[FR] Langage assembleur sur ez80 - Tutoriel

Regroupement de tous les tutoriaux z80 (82/83/84)

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude Epharius » 19 Mai 2017, 21:48

Yo les pitchouns, j'avais la flemme de programmer, alors du coup devinez ce que j'ai fait... j'ai écrit un tutoriel sur la programmation :troll:
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: Tout sélectionner
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...
Le mode qui va être utilisé le plus souvent est le deuxième mode, l'unique scan. Le code minimal pour lire le clavier est par conséquent :
Code: Tout sélectionner
   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 :
%
00110
011100
10110


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: Tout sélectionner
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.
Le projet Geometry Dash est en cours ! N'hésitez pas à aller jeter un coup d’œil au topic du projet !

Unis par la flèche sacrée de cupidon :favorite:
Image
Avatar de l’utilisateur
EphariusPremium
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Prochain niv.: 77.4%
 
Messages: 931
Images: 4
Inscription: 08 Déc 2014, 17:38
Genre: Homme
Calculatrice(s):
Classe: Prépa MPSI Descartes Tours
YouTube: yes I tube

En ligne

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude MMBC_Chris » 25 Mai 2017, 07:51

Hello.

Très bon tutoriel ! :D
Cependant il sera aimable de rajouter comment faire les conditions et les boucles....

Aussi est il possible de faire par exemple
Code: Tout sélectionner
    call foo
    ret

foo:
    call _rgebf
    ld hl, $bfdf
ImageImage
Image
Avatar de l’utilisateur
MMBC_ChrisPremium
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Prochain niv.: 89.8%
 
Messages: 84
Images: 1
Inscription: 16 Mai 2017, 19:20
Genre: Homme
Calculatrice(s):
Classe: STI3D :troll:
YouTube: MMBC Productions
Facebook: Ced Cad

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude Epharius » 25 Mai 2017, 21:14

Non à la fin de ton call tu dois avoir un ret pour dire que c'était la fin de ta routine (ta fonction un peu comme le Return en C++)
Le projet Geometry Dash est en cours ! N'hésitez pas à aller jeter un coup d’œil au topic du projet !

Unis par la flèche sacrée de cupidon :favorite:
Image
Avatar de l’utilisateur
EphariusPremium
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Prochain niv.: 77.4%
 
Messages: 931
Images: 4
Inscription: 08 Déc 2014, 17:38
Genre: Homme
Calculatrice(s):
Classe: Prépa MPSI Descartes Tours
YouTube: yes I tube

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude Dark coco » 27 Mai 2017, 01:20

Epharius super que tu as eu le temps de faire ça et en plus j'ai appris des infos sinon je suis pas si c'est moi mais la mis en page est mieux qu'avant enfin bref si vous avez une partie que vous voulez que je fasse je suis preneur ;)
Autre truc que je viens de voir il y a une petite erreur lors que l'explication des registres "IEF2 ADL est un bit indiquant que les interruptions de niveau 2 sont actives" ça serait plutôt IEF2 à la place ADL voilà :) .
(21:48:26) Hamza.S: Dark_coco : tu a écris 2 phrases sans faute
Avatar de l’utilisateur
Dark cocoProg.
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Prochain niv.: 25.5%
 
Messages: 78
Inscription: 15 Jan 2017, 14:39
Genre: Homme
Calculatrice(s):
Classe: term tfca

En ligne

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude MMBC_Chris » 07 Juil 2017, 09:20

Bon, sinon quelqu'un sait comment faire du double buffering ? En 8bpp on peut utiliser le reste de la vRam comme buffer mais après, il faut echanger les pixels un par un avec une routine (très) lente où y'a une technique spéciale pour inverser l'écran et le buffer (genre changer une valeur à une adresse spécifique) ?
ImageImage
Image
Avatar de l’utilisateur
MMBC_ChrisPremium
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Prochain niv.: 89.8%
 
Messages: 84
Images: 1
Inscription: 16 Mai 2017, 19:20
Genre: Homme
Calculatrice(s):
Classe: STI3D :troll:
YouTube: MMBC Productions
Facebook: Ced Cad

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude Adriweb » 07 Juil 2017, 09:26

Avatar de l’utilisateur
AdriwebAdmin.
Niveau 16: CC2 (Commandeur des Calculatrices)
Niveau 16: CC2 (Commandeur des Calculatrices)
Prochain niv.: 37.4%
 
Messages: 11251
Images: 830
Inscription: 01 Juin 2007, 00:00
Localisation: France
Genre: Homme
Calculatrice(s):
Classe: (ingénieur)
Twitter: adriweb
GitHub: adriweb

Re: [FR] Langage assembleur sur ez80 - Tutoriel

Message non lude Epharius » 07 Juil 2017, 12:44

Tu sais surement le principe de la chose mais j'explique pour ceux qui voudraient savoir ce que c'est :

Le double-buffering est donc une technique qui consiste à avoir deux espaces mémoire (buffer) de 320*240o chacun (en partant du principe que nous sommes en 8bpp) : l'un va être affiché à l'écran, pendant que l'autre va être modifié par le programme, le but étant d'éviter de pouvoir voir l'écran redessiné chaque frame. Quand on a fini de dessiner, on affiche le buffer où l'on a dessiné la frame suivante, et les deux espaces échangent leur rôle : le premier va devenir l'espace où on va dessiner la nouvelle frame et le deuxième va être affiché à l'écran.

Pour faire du double-buffering, la seule chose que tu as besoin de retenir c'est :
Code: Tout sélectionner
   ld hl,vRam
   ld (mpLcdBase),hl

En gros, mpLcdBase est l'adresse du port mappé en mémoire qui gère la position dans la mémoire de l'endroit que le LCD va afficher. Par défaut, sa valeur est à $D40000 ce qui correspond au début de la vRam.
Dans notre cas, les deux buffers sont à $D40000 et à $D40000+320*240.
Il suffit donc d'alterner entre ces deux buffers à chaque tour de boucle par exemple avec le code suivant :
Code: Tout sélectionner
; Swaping Vram Buffers (double-Buffering)
   ld hl,vRam
   ld bc,(mpLcdBase)
   or a
   sbc hl,bc 
   add hl,bc              ; Is the current buffer the screen buffer?
   jr nz,notCurrBuf
   ld hl,vram+(lcdWidth*lcdHeight)
notCurrBuf:
   ld (currentDrawLoc),bc ; Set the new buffer location to the old screen pointer
   ld bc,mpLcdIcr
   ld a,(bc)
   or a,4 ; bitLcdLnBuim
   ld (bc),a
   ld (mpLcdBase),hl
waitForSync:            ; Wait fot the LCD to be ready to update
   ld a,(mpLcdRis)
   and a,4 ; bitLcdLnBuim
   jr z,waitForSync

currentDrawLoc:
   .dl vram+(lcdWidth*lcdHeight)

Bon, c'est un code que j'ai trouvé sur le site qui a fait quelques tuto sur l'asm eZ80 (mais honte à moi je n'arrive plus à retrouver le lien), il est assez simple à comprendre : premièrement on change currentDrawLoc dont la valeur est l'adresse du buffer sur lequel il faut dessiner (en fait c'est juste l'opposé de mpLcdBase), puis on change le buffer qui va être affiché dans mpLcdBase, enfin on attend que la modif soit terminée avec une petite pause.

Ce qui change au niveau du programme, c'est qu'au lieu de mettre ld hl,vRam+45 pour écrire sur le pixel n°46, il faudra faire ld hl,(currentDrawLoc) / ld de,45 / add hl,de ce qui prend plus de temps malheureusement.
De plus, les changements que tu fais sur un buffer, tu devras les refaire par la suite sur le deuxième buffer ce qui nécessite de penser à la méthode qu'on va utiliser avant de faire son programme : soit on redessine tout à chaque fois et il n'y a pas de problème, soit on fait des changements "relatifs" (scrolling avec un LDIR, etc) et dans ce cas il faut s'organiser.

Si tu as des questions n'hésite pas, j'ai un peu abrégé parfois :p
Le projet Geometry Dash est en cours ! N'hésitez pas à aller jeter un coup d’œil au topic du projet !

Unis par la flèche sacrée de cupidon :favorite:
Image
Avatar de l’utilisateur
EphariusPremium
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Prochain niv.: 77.4%
 
Messages: 931
Images: 4
Inscription: 08 Déc 2014, 17:38
Genre: Homme
Calculatrice(s):
Classe: Prépa MPSI Descartes Tours
YouTube: yes I tube

Précédente

Retourner vers Tutoriaux

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 3 invités

-
Rechercher
-
Sujets à la une
"NumWorks++": Challenge de modification matérielle pour rajouter une puce de mémoire Flash !
Offre TI-Planet/Jarrety pour avoir la TI-83 Premium CE avec son chargeur pour 79,79€ port inclus !
Offre TI-Planet/Jarrety pour avoir la TI-Nspire CX CAS à seulement 130€ TTC port inclus!
Jailbreake ta TI-Nspire avec Ndless et profite des meilleurs jeux et applications !
Transforme ta TI-Nspire CX en console Game Boy Advance!
12345
-
Donations/Premium
Pour plus de concours, de lots, de tests, nous aider à payer le serveur et les domaines...
PayPal : paiement en ligne sécurisé - secure online payments
Découvrez les avantages d'un compte donateur !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partenaires et pub
Notre partenaire Jarrety 
-
Stats.
340 utilisateurs:
>310 invités
>26 membres
>4 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Autres sites intéressants
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)