Programmation en
assembleur sur HP49G
Les interruptions (2): gestion des touches par bufferisation |
Version du 23/04/2001
Introduction :Tout d'abord, comme pour la première partie, il n'est pas, je pense, nécessaire d'être un Dieu en assembleur pour comprendre (la preuve est que j'ai compris...). Il faut évidement des bases de programmation en assembleur et surtout savoir un peu Programmer au sens général du terme (algo, réfléxion...). Comme j'ai voulus que ce "cours" puisse être compris par le plus grand nombre, les plus expérimentés pourront trouver certaines remarques ridicules voir intutiles mais je pense qu'elles pourront servir à d'autres. Cette documentation se décompose en plusieurs parties. Une première présentera le fonctionnement d'un buffer et l'utilité qu'on pourra en faire. Suivra un algo détaillé et commenté de la gestion des touches par bufferisation. Puis son équivalent en assembleur accompagné de fonctions utilisant ce principe de gestion des touches. Tous les programmes sont écris avec la syntaxe MASD. Je voudrais enfin signaler que, comme pour la première partie, certains passage sont tirés ou inspirés de PowerPaint de dam's. Buffer : principe, utilitéUn buffer est une "Zone-mémoire destinée au stockage temporaire d'informations en attente de traitement" (Voyage au centre de la HP48G/GX). Un buffer est une structure (une file, je pense) de type FIFO, c'est à dire que la première information entrée dans la file est la première à en sortir. On ne peut y appliquer que peu de traitement : ajouter un élément, prendre ou voir un élément et on ne connait que peu de choses : indice du sommet (ou adresse), nombre d'éléments,... Sur les HP, le buffer clavier, comme le buffer de transmission, est un buffer circulaire de 32 quartets, ce qui permet de placer 16 touches codées chacune sur 2 quartets. C'est un buffer circulaire, ce qui veut dire qu'on ne fait qu'incrémenter les deux variables indiquant la première case utilisée et la première case vide. Comme ces deux variables sont utilisées sur un quartets (16 valeurs différentes), une fois arrivée la valeur #Fh, si on incrémente on retombe sur #0h. On a donc fait "un tour" de buffer. Il existe enfin deux types de buffers. Pour le premier on n'écrit dans le buffer que s'il est non plein. C'est évident au premier abord mais il existe un deuxième type de buffer, appelé aussi overflow. Pour les buffer de ce type, on écrit toujours dans le buffer mais on incrémente l'indice de la prochaine case à écrire que si le buffer n'est pas plein. On peut donc écrire sur la dernière touche. Maintenant, l'utilité. Tout d'abord un point intéressant est de tout simplement savoir et pouvoir le faire :), même si on ne l'utilise pas (ce qui serait dommage). Plus sérieusement, tout dépend de la façon dont on le programme et utilise. On peut le programmer de deux façons différentes : entièrement intégré au gestionnaire d'interruption, ou en partie dans le gestionnaire d'interruption et dans le programme en lui-même. Pour la première solution, le placement des touches dans le buffer ainsi que les exécutions qui leurs sont associées sont dans le gestionnaire d'interruption. Ceci implique qu'à aucun moment on ne test les touches dans le programme principal, tout étant géré lors des interruptions. On peut donc observer un gain de temps car on ne test plus les touches. Dans la deuxième solution, on place les touches dans le buffer à partir du gestionnaire d'inter et, dans le programme principal, on test s'il y a des touches dans le buffer. Si aucune touche est pressée, on gagne donc du temps car on ne test pas toutes les touches à chaque tour de boucle mais seulement s'il y a réellement une touche de pressée. Seule cette deuxième solution sera traitée par la suite. Le fait de placer les touches dans un buffer peut également faciliter la gestion de la durée d'appui d'une touche, les combinaisons de touches (prochaine documentation) par exemple. Algo de gestion des touches par bufferisationOn utilise un tableau TabClavier de #99h quartets, dans lequel est noté sur 3 quartets le temps d'appui d'une touche en fonction de la période des interruptions non liées au clavier (VBL pour le plus courant). On utilise également un tableau TabOutIn de #132h quartets contenant les codes OUT IN de chaque touche sur 6 quartets (autre solution : TabOutIn est un pointeur sur un tableau contenu dans le programme). Les touches sont évidement placées dans le même ordre.
On parcourt TabClavier
Si les codes ne correspondent pas c'est qu'on a relaché la touche, mais on en a surement pressé une autre. -> On met à zéro la valeur du temps d'appui pour cette touche.
-> La touche reste appuyée
-> Aucune touche n'a été précédemment appuyée.
Voila, c'était pas si compliqué ! On parcourt TabClavierOn pointe sur TabClavier
-> On pointe trois quartets plus loin
Test de la valeur renvoyée Si la valeur est nulle
-> On pointe sur TabOutIn + 6 * indice de la touche
On les place dans OUT On récupère IN On compare par rapport au couple OUT/IN du tabeau Si les codes ne correspondent pas -> On met la valeur du temps d'appui de la touche à zéro
-> On incrémente sa valeur dans TabClavier Test de toutes les touches On pointe sur la premi&egrae;re
case de TabClavier
On sort -> On met à zéro le temps d´appui de la touche
On boucle tant qu'on a pas parcouru tout le tableau } Ecriture du buffer On pointe sur la zone mémoire qui
contient l'indice de la case dans
l'adresse dans laquelle on doit écrire
Récupération d'une touche On pointe sur le nombre de touches
dans le buffer Cette durée dépend éidemment du temps mis par horloges à passer à zéro (intervalle entre deux interruptions horloges) On pointe en TabClavier + 3 * indice
de la touche Un peu facile, non ? Attente de l'appui d'une toucheOn lance la fonction récupérant une
touche dans le buffer Ca tout le monde aurait pu le trouver... Attente du relachement de toutes les touchesOn pointe en TabClavier On ne doit pouvoir sortir que si tout le tableau est à zéro Programme équivalentJ'ai choisi de ne pas commenter beaucoup les programmes pour deux raisons. La première est que c'est long et fastidieux :). La deuxième est que ça vous oblige à réfléchir, seul solution pour comprendre, et à comparer avec l'algo ce qui permet de savoir ce qu'on fait et surtout à quoi ça sert (je fournis également les sources d'un petit programme qui sont elles un peu plus commentées...(bientôt dispo)) Adresses en ROMBuffer : #8066Bh (32d quartets = 20h) NbTouchesBuffer sur 2 quartets TabClavier doit être initialisé à zéro,
tout comme KeyStart et KeyEnd. Cette représentation a été choisi
pour une facilité de compréhension. Par
contre dans les sources, vous trouverez
non pas TabOutIn comme un Tableau de 132q
mais comme un pointeur sur une chaine
composée des code OUT/IN, présentée de
la manière suivante : $code1code2... Le minimum nécessaire à savoir sur les gestionnaires d'interruption est "détaillé" dans la doc sur le détournement des inter. Voici la partie qui nous intéresse dans le gestionnaire : GOSUB
Parc_TC Cette partie n'est rien d'autre qu'un
appel à des routines que je sépare pour
plus de lisibilié *Parc_TC Test de la valeur mise dans C.B (temps d'appui)
?C#0.X SKIPYES % Si le temps est à zéro, aucune touche n'a été pressée
GOSUB Test_Toutes_Touches }
B=A.A A+A.A A+B.A A+A.A LC(5)TabOutIn C+A.A D1=C C=0.A C=DAT1.X OUT=C=IN D1+3 A=0.A A=DAT1.X C&A.X ?C#0.X SKIPYES % Si les codes sont différents
A=0.X DAT0=A.X % D0 pointe sur la case de TabClavier GOSUB Test_Toutes_Touches }
A=DAT0.X A+1.X DAT0=A.X } On test toutes les touches
LC 0031 D=C.A A=0.B D0=(5)TabClavier D1=(5)TabOutIn
C=0.A C=DAT1.X OUT=C=IN B=C.X D1+3 C=DAT1.X C&B.X ?C=0.X SKIPYES % Si les codes correspondent
C=DAT0.X C+1.X DAT0=C.X GOSUB W_Buffer % On écrit dans le buffer RTN }
C=0.X DAT0=C.X } D1+3 % On passe à la case suivante de TabOutIn A+1.B % On incrémente l'indice de la cas en cours C=RSTK C=A.B ?C>D.B
RSTK=C UP2 } } Ecriture du buffer *W_Buff *Retourne_Touche *Attente_Touche *Temps_Touche
Il existe d'autres façons pour gérer
les touches par bufferisation selon les
utilisations qu'on veut en faire. J'ai présenté
ici la solution la plus complète, elle
peut être utilisée avec n'importe quel
programme. Son avantage est d'avoir en mémoire
le temps d'appui de toutes les touches. On
peut donc utiliser cette méthode pour gérer
l'appui simultané de plusieurs touches
(prochaine partie...). Pour ceux qui n'ont pas compris, si il y a des erreurs ou des modifications à faire ou pour tout autre chose : yves.brissaud@wanadoo.fr ainsi que le forum d'HP-Sources |