SOMMAIRE EDITO COURRIER L'EQUIPE ACTUALITE NEWS CONCOURS EXTERNAL ASM-INIT ASM-PRATIK INTERRUPTION HARD DUNE EDEN HPMARRIO INTERVIEW BOOK HP92
HPGrâal Numero 1

Les Interruptions

Remarque préliminaire : cet article ne vise pas à décrire ce que sont les interruptions mais plutôt à expliquer à quoi elles peuvent servir pour le programmeur que vous êtes ! Pour plus d'informations sur les interruptions je vous conseilles fortement de vous reporter aux deux fichiers HPREGINT et HPMJSINT (disponibles sur PULSAR bien entendu).

  1. Présentation générale des interruptions

    Une interruption a lieu lorsque l'un des événements suivants se produit :

      • Horloges 1 ou 2 passant à zéro.
      • Carte mémoire retirée.
      • Batteries faibles.
      • RAM corrompue.
      • Réception d'un octet sur le port infrarouge/RS232.
      • Touche du clavier enfoncée.

    Lorsque l'un de ces événements a lieu, le SATURN va automatiquement aller en #0000Fh, où se trouve la routine de gestion des interruptions. On peut masquer certaines interruptions, de trois manières différentes :

      • Grâce à l'instruction INTOFF, l'appui sur une touche ne provoquera plus d'interruptions, sauf pour la touche ON qui provoque TOUJOURS une interruption !
      • On peut aussi interdire toutes les interruptions par l'intermédiaire de l'instruction ST=0 15. En effet il ne peut pas y avoir deux interruptions en même temps. Avec le flag 15, la routine de gestion des interruptions annule le traitement de l'interruption en cours et au lieu de retourner au programme en cours par un RTI, la routine revient par un RTN. Or le RTI permet justement à une autre interruption d'avoir lieu, contrairement au RTN qui empêche une autre interruption d'avoir lieu.
      • On peut aussi, par l'intermédiaire de la RAM I/O, autoriser ou non le déclenchement d'une interruption venant des horloges et du port série (cf. Voyage au centre de la HP pour plus de détails).

  2. Intérêts des interruptions

    Le principal intérêt des interruptions c'est qu'on peut détecter des événements sans les tester sans arrêt ! Par exemple la HP ne s'occupe presque jamais de tester le clavier puisque à chaque fois qu'on appuie sur une touche, une interruption a lieu et la touche est stockée dans le buffer clavier ! Pour les programmes en niveaux de gris par exemple, il est très lourd de tester à chaque opération du jeu de savoir s'il est temps de changer d'écran. Avec le détournement d'interruptions, il vous suffit de mettre une valeur, dans l'horloge 2, correspondant à un rafraîchissement écran (ou 2 suivant l'écran à afficher). Ainsi, à chaque interruption de celle-ci, on échange les écrans et on recharge une nouvelle valeur dans l'horloge 2 ! Ainsi plus rien ne vous empêche d'effectuer des opérations sur plusieurs VBL puisqu'à chaque fois qu'il sera temps d'afficher un nouvel écran cela se passera automatiquement sans que vous vous en rendiez compte !

  3. Comment détourner les interruptions de la HP ?

    Le principal problème pour détourner les interruptions est que le gestionnaire est en #0000Fh, or à cette adresse il y a la ROM. Le moyen le plus pratique est de déplacer la RAM en #00000h, puis de coder un GOVLNG vers votre gestionnaire d'interruptions. Il faut tout d'abord interdire les interruptions (pour pouvoir déplacer la RAM) et autoriser les interruptions de l'horloge 2 puis on met une valeur dans celle-ci pour que les interruptions s'initialisent toutes seules.
    
      GOSBVL  0679B
    
      GOSBVL  01115
    
    
    
      % On enlève les menus
    
      D1=     00128
    
      LC      F
    
      DAT1=C  1
    
    
    
      % Récupération d'une adresse paire (écran
    
      % oblige) dans la zone mémoire libre, dans
    
      % notre exemple c'est cette zone mémoire
    
      % qui va être affichée
    
    
    
      A=B     A
    
      A=A+1   A
    
      ABIT=0  0
    
    
    
      % Adresse qu'utilisera votre gestionnaire
    
      % pour connaître l'adresse de l'écran à
    
      % afficher
    
      D0=     80153
    
      LC      80000
    
      A=A-C   A
    
      DAT0=A  A
    
      % On pointe sur le deuxième écran
    
      D0=D0+  5
    
      LC      00880
    
      A=A+C   A
    
      DAT0=A  A
    
    
    
      % Initialisation de l'horloge 2
    
      D0=     0012E
    
      LC      30
    
      DAT0=C  B
    
    
    
      % On va mettre une valeur dans l'horloge
    
      % pour qu'elle s'initialise toute seule
    
      D0=     38
    
      C=0     W
    
      C=C+1   A
    
      DAT0=C  8
    
    
    
      % On pointe sur notre routine de gestion
    
      % d'interruptions
    
      A=PC
    
      GOINC   MYINT
    
      A=A+C   A
    
    
    
      % Puis on teste si elle est en RAM ou non
    
      LC      C0000
    
      ?A>C    A
    
      GOYES   PAS.EN.RAM
    
      LC      80000
    
      A=A-C   A
    
      *PAS.EN.RAM
    
      % Puis on sauvegarde l'adresse pour une
    
      % utilisation future
    
      D0=     800A2
    
      DAT0=A  A
    
    
    
      % On appelle la routine qui va se charger
    
      % de déplacer la RAM
    
      GOSUBL  INIT.INT
    
    
    
      % On attend une touche
    
      *WAIT.KEY
    
      LC      1FF
    
      GOSBVL  00017
    
      ?C=0    X
    
      GOYES   WAIT.KEY
    
    
    
      % On appelle la routine qui va se charger
    
      % de replacer la RAM
    
      GOSUBL  STOP.INT
    
    
    
      % On remet les pointeurs écrans, menus
    
      GOSBVL  01C7F
    
      % On réautorise les interruptions
    
      GOSBVL  010E5
    
      % On vide le buffer clavier
    
      GOSBVL  00D57
    
      % On sort
    
      GOVLNG  05143
    
    
    
      % On link le source qui déplace la RAM
    
      'RAMINT
    
      % et celui qui contient votre gestionnaire
    
      % d'interruptions
    
      'MYINT
    
      @"
    
      
    Pour déplacer la RAM il ne faut pas que le programme qui la déplace soit lui même en RAM. Il faut en effet que tous les CONFIG/UNCNFG soient à une adresse fixe ! La seule solution est de charger la pile RSTK d'adresses en ROM qui vont s'appeler tour à tour, grâce aux RTN, pour revenir au programme après le déplacement de la RAM. La RAM va donc recouvrir la ROM et les routines de tests de touches qui sont indispensables. Il faut donc recoder l'instruction C=IN à une adresse paire, ce qui va être fait en même temps que le codage du GOVLNG en #0000Fh car tout tient dans un champ W comme le montre le tableau :

    # F
    # 10
    # 11
    # 12
    # 13
    # 14
    # 15
    # 16
    # 17
    # 18
    # 19
    # 1A
    # 1B
    # 1C
    # 1D
    # 1E
    8
    D
    ?
    ?
    ?
    ?
    ?
    0
    8
    0
    1
    8
    0
    3
    0
    1
    Codage du GOVLNG vers votre gestionnaire
    (*)
    OUT=C
    C=IN
    RTN
    (*) Sert uniquement pour que l'instruction C=IN soit à une adresse paire.

    Au lieu de faire habituellement un GOSBVL 01EEC, on fera un GOSBVL 00017.

    
      "*INIT.INT
    
    
    
      % On sauvegarde les 16 quartets que l'on va
    
      % utiliser en # 8000Fh, en # 80092h
    
      D0=     8000F
    
      A=DAT0  16
    
      D1=     80092
    
      DAT1=A  16
    
    
    
      % On se prépare à poker le GOVLNG vers
    
      % votre gestionnaire et le nouveau OUT=C
    
      % C=IN RTN en # 00017h
    
      P=      6
    
      LC      10308108 % OUT=C C=IN RTN
    
      P=      0
    
      D1=     A2
    
      C=DAT1  A % Adresse de votre gestionnaire
    
      D=C     A
    
      CSL     W
    
      CSL     W
    
      LC      D8 % Codage du GOVLNG
    
      DAT0=C  16
    
    
    
      % On teste si le gestionnaire est en RAM ou
    
      % pas, pour savoir si on doit revenir après
    
      % le déplacement de la RAM
    
      D=D+D   A
    
      GOC     NOT.IN.RAM
    
      C=RSTK
    
      LA      80000
    
      C=C-A   A
    
      RSTK=C
    
      *NOT.IN.RAM
    
    
    
      D0=     05
    
      C=DAT0  A % Taille de la RAM
    
      B=C     A
    
      LC      40154 % RTI
    
      RSTK=C
    
      LC      41535 % CONFIG RTN
    
      RSTK=C
    
      LC      40004 % C=0 A RTN
    
      RSTK=C
    
      LC      41535 % CONFIG RTN
    
      RSTK=C
    
      LC      66B75 % BCEX RTN
    
      RSTK=C
    
      LC      80000
    
      GOVLNG  4049B % UNCNFG RTN
    
      % Récapitulons : cet empilage va réaliser
    
      % (avec B contenant la taille de la RAM en
    
      % complément à 2 pour être utilisé par
    
      % l'instruction CONFIG)
    
      % LC 80000
    
      % UNCNFG
    
      % BCEX
    
      % CONFIG
    
      % C=0 A
    
      % CONFIG
    
      % RTI (on réinitialise les interruptions,
    
      % en revenant au programme principal)
    
    
    
      *STOP.INT
    
      C=0     X
    
      OUT=C
    
      % On remet l'horloge 2 dans son état
    
      % initial
    
      LC      10
    
      D0=     0012E
    
      DAT0=C  B
    
    
    
      % On teste si le gestionnaire est en RAM ou
    
      % pas, pour savoir si on doit revenir après
    
      % le déplacement de la RAM
    
      D0=     000A2
    
      C=DAT0  A
    
      C=C+C   A
    
      GOC     NOT.IN.RAM2
    
      C=RSTK
    
      LA      80000
    
      C=C+A   A
    
      RSTK=C
    
      *NOT.IN.RAM2
    
    
    
      % Restauration des 16 quartets utilisés
    
      D0=     92
    
      A=DAT0  16
    
      D1=     0000F
    
      DAT1=A  16
    
    
    
      % Remise en place de la RAM
    
      % Adresse de la routine s'occupant de
    
      % replacer la RAM après un ON-C :
    
      LC      0224F
    
      RSTK=C
    
      C=0     A
    
      GOVLNG  4049B % UNCNFG
    
      @"
    
      
  4. Comment écrire le nouveau gestionnaire d'interruptions ?

    La routine de gestion d'interruptions va s'occuper de swapper les 2 écrans pour former l'image en niveaux de gris. Comme vous vous en doutez cette routine doit ABSOLUMENT sauvegarder les registres qu'elle pourrait modifier car elle peut être appelée n'importe où dans votre code ! La routine sauvegarde les registres suivants :

      • La CARRY (ST=0 15 : pas de CARRY, ST=1 15 : CARRY)
      • C(A) (Sauvegardé dans RSTK)
      • C(5-15) et D0.
      • SB, P et le mode hexadécimal/décimal.

    Récapitulons toutes les occupations mémoire nécessaire au fonctionnement de notre gestionnaire :

    Adresse Contenu
    # 00092h Sauvegarde des 16 quartets utilisés en # 8000F
    # 000A2h Sauvegarde de l'adresse de notre gestionnaire
    # 00140h Sauvegarde de C(5-15) et D0
    # 00150h Sauvegarde de SB, P et le mode hexadécimal/décimal
    # 00153h Adresse du premier écran à afficher
    # 00158h Adresse du deuxième écran à afficher

    Si vous devez utiliser plus de registres dans votre nouveau gestionnaire d'interruptions il vous faudra changer cette routine pour pouvoir sauvegarder ces registres. Le flag 14 permet de savoir quel écran est à afficher, il ne faut donc pas le modifier dans votre code principal mais il peut être testé pour savoir si l'image a fini d'être affichée.
    
      "*MYINT
    
      % Début de la sauvegarde des registres
    
      ST=0    15
    
      GONC    NO.CARRY
    
      ST=1    15
    
      *NO.CARRY
    
      RSTK=C
    
      CD0EX
    
      D0=     00140
    
      DAT0=C  16
    
      C=0     A
    
      ?SB=0
    
      GOYES   NO.SB
    
      C=C+1   A
    
      *NO.SB
    
      CPEX    1
    
      P=      2
    
      C=C-1   P
    
      P=      0
    
      SETHEX
    
      D0=     50
    
      DAT0=C  3
    
      % Fin de la sauvegarde des registres
    
    
    
      % On teste si c'est bien l'horloge 2 qui a
    
      % provoqué une interruption
    
      D0=     2F
    
      C=DAT0  B
    
      ?CBIT=0 3
    
      GOYES   FIN.INT
    
    
    
      % On se synchronise avec le balayage écran
    
      D0=     28
    
      *WAIT.VBL
    
      C=DAT0  B
    
      C=C+C   B
    
      C=C+C   B
    
      ?C(0    B
    
      GOYES   WAIT.VBL
    
    
    
      % On cherche le bon écran à poker en
    
      % # 00120h en fonction du flag 14
    
      D0=     53
    
      ?ST=0   14
    
      GOYES   1ER.ECRAN
    
      D0=     58
    
      *1ER.ECRAN
    
      % Récupération de l'adresse de écran à
    
      % afficher
    
      C=DAT0  A
    
    
    
      % On le poke
    
      D0=     20
    
      DAT0=C  A
    
    
    
      % On recharge l'horloge 2 avec la valeur
    
      % qui convient en fonction de écran à
    
      % afficher :
    
      % # 80h (qui correspond à 1/64ème de
    
      % seconde soit 1 VBL) pour le premier écran
    
      % et
    
      % # 100h (qui correspond à 2/64ème de
    
      % seconde soit 2 VBL) pour le deuxième
    
      % écran
    
      % Mais on préfère mettre moins pour pouvoir
    
      % se synchroniser parfaitement et avoir des
    
      % niveaux de gris parfaits
    
      D0=     38
    
      C=0     W
    
      LC      7D
    
      ?ST=0   14
    
      GOYES   PREMIER.ECRAN
    
      LC      FD
    
      ST=0    14
    
      GONC    ECRIRE.HORLOGE
    
      *PREMIER.ECRAN
    
      ST=1    14
    
      *ECRIRE.HORLOGE
    
      DAT0=C  8
    
    
    
      *FIN.INT
    
      % Restauration des registres
    
      D0=     50
    
      C=DAT0  3
    
      P=      2
    
      C=C+1   P
    
      GOC     HEX
    
      SETDEC
    
      *HEX
    
      P=C     1
    
      CSRB    B
    
      D0=     40
    
      C=DAT0  16
    
      D0=C
    
      C=RSTK
    
      ?ST=1   15
    
      GOYES   CARRY
    
      *CARRY
    
      RTI
    
      @"
    
      
Cette routine est donnée à titre d'exemple, on pourrait rajouter d'autres fonctionnalités :

    • Gestion du port IR pour jeux à 2.
    • Gestion des touches par bufferisation.
    • Faire jouer de la musique en tâche de fond.
    • Emuler du multitâche (enfin avec les limitations de la HP bien entendu).
Note : Il ne faut pas oublier de tester si on n'est pas en face d'une carte mergée car dans ce cas il se pourrait qu'une partie du programme soit déplacée et pas l'autre d'où apparition d'un problème...

CHL


Des questions:hpgraal@hotmail.com
Un mot au WEBMASTER?:gissehel@mygale.org
Passez donc sur pulsar:Le site pulsar