Intérruption Raster et Intérruptions DMA.
Notre gx4000 et notre cpc+ disposent de 4 interruptions DMA différentes.
- Une interruption raster
- 3 interruptions DMA son
Pour les utiliser comme toujours, n'oubliez pas de délocker l'ASIC et de connecter la page I/O ASIC avant d'envoyer votre valeur.
L'interruption DMA raster:
En mode normal, la seule interruption ayant court est l'interruption envoyée par le Gate Array. Celle-ci est envoyée 300 fois par seconde.
L’inconvénient de cette interruption est principalement que vous ne pouvez choisir le moment où elle a lieu avec précision.
Aussi, pour se caler dessus, vous n'aurez le choix qu'entre l'un des 6 moments ou elle a lieu par VBL.
Les interruptions raster corrigent le tir. Avec elles,vous pourrez choisir à la ligne prêt quand elles seront envoyées.
Pour décider de la ligne à laquelle vous voulez une interruption, vous devez envoyer au PRI en #6800 le numéro de la ligne à laquelle vous voulez cette interruption.
En envoyant 2 dans PRI, vous aurez donc une interruption raster en ligne 2.
Les interruptions raster sont prises en compte pendant la HBL. Aussi vous serez donc précis à la ligne.
Lorsqu'une interruption raster est mise, les interruptions GA sont annulées: il n'y en aura plus.
Ainsi, si vous mettez une seule interruption raster par écran, il n'y aura que cette interruption et aucune interruption GA.
Si PRI=0 alors il n'y aura pas d'int raster et le GA rétablit ses interruptions.
Vous vous demandez sans doute comment avoir plusieurs int raster par écran ?
Rien de plus simple: vous devez les programmer les unes après les autres.
ex:
LD A,2 LD (#6800),A ;interruption ligne 2 HALT ;on attend l'interruption. Au HALT nous sommes donc à la ligne 2 LD A,10 LD (#6800),A ;interruption ligne 10 HALT ;vous êtes à la ligne 10 ...
Comme vous l'avez remarqué, PRI est sur 8 bits. Ceci signifie que vous ne pouvez mettre un numéro de ligne supérieur à 255.
Hors sur un moniteur de CPC+ chaud on voit un peu plus de 280 lignes...
Comment faire pour avoir une int raster après 255 lignes ?
Et bien là encore c'est simple: PRI boucle à 0 après avoir atteins 255 !!!
Ainsi, si après avoir dépassé la ligne 10, vous demandez une int raster ligne 8, vous aurez donc une int raster à la ligne 255+8=263.
Dernier petit point à aborder: PRI est fonction des registres du CRTC.
Aussi, celui-ci bouclera à 0 au bouclage de C4 du CRTC.
Attention donc !!! Ceci est valable aussi pour les interruptions DMA.
Ainsi si vous faites de la rupture d'écran (splitscreen) avec le CRTC, n'oubliez pas que les int pourront se répéter.
Les interruptions DMA son:
Nous disposons de 3 DMA son.
Ceux-ci n'ayant rien à voir avec les 3 voix son du cpc.
Chaque DMA peut exécuter du son sur chaque voix.
Mais chaque DMA dispose d'une int DMA son.
Aussi nous avons 3 DMA pouvant chacun provoquer une int.
Comment ça se passe ?
Il vous faudra lire l'article sur les DMA son pour bien comprendre le fonctionnement.
Mais je vais ici exposer juste ce qu'il faut pour mettre en place les int DMA son.
Chaque DMA son peut lire une DMA-list.
Une DMA list c'est en gros une liste (forcément en RAM centrale) qui comprend des instructions dans un langage spécifique.
Pour déterminer l'adr d'une DMA-list voici un tableau vous donnant les adresses ou les poker:
DMA n° | ADRESSE (SAR) |
0 | #6C00-#6C01 |
1 | #6C04-#6C05 |
2 | #6C08-#6C09 |
Vous donnerez donc à ces adresses, l'adresse de votre DMA list (si vous n'utilisez qu'une DMA list, vous n'avez pas besoin de préciser les autres).
Pour provoquer une interruption DMA vous devrez utiliser l'instruction INT qui a pour valeur #4010.
A chaque fois que cette valeur sera présente dans votre DMA-list, une interruption sera générée.
Notez que toutes les instructions DMA sont sur 2 octets et qu'une DMA-list commence TOUJOURS sur un octet pair et le poids faible de votre instruction doit être en tête (donc sur l'octet pair).
A chaque HBL, une instruction est lue pour chaque DMA list. Ce qui nous fait une instruction par ligne et par DMA.
L’intérêt de ces int DMA peut être par exemple de synchroniser quelque chose avec la musique ou... de générer une liste d'interruptions DMA par écran.
Je vous ai concocté un petit exemple afin de vous montrer comment générer une liste d’interruptions.
Le programme est simple et très commenté afin que tous s'y retrouvent.
Il fait appel à quelques autres chapitres comme par exemple comment changer les couleurs avec le GA ou utiliser la pile.
En lui même voici ce que fait se programme:
nous aurons une interruption raster, qui, quand elle arrivera, sautera à une routine qui lancera une DMA-list et l'initialisera (donc la remettra à 0 à chaque int raster).
Cette int raster fera un raster bleu afin de voir ou elle a lieu sur l'écran.
D'autre part nous aurons une routine de raster rouge, dans laquelle sauteront toutes les interruptions DMA son 1.
Enfin notre DMAlist contiendra uniquement des int DMA.
Ainsi, quand l'int raster sera rencontrée, notre DMAlist sera lancée depuis son début.
La DMAlist génèrera des int DMA son 1.
Chaque fois qu'une int DMA son 1 aura lieu vous aurez un raster rouge.
Vous obtiendrez à l'écran ceci:
Et voici le programme d'exemple:
ORG #8000 ;on se met en #8000 DMALIST DS 100*2,0 ;on remplis 100 fois 2 octets de valeur 0 ;ceci nous sert a préparer notre DMA liste en la remplissant de 0 ;******************************************************************************** ;***************************** ROUTINE PRINCIPALE ******************************* ;******************************************************************************** ORG #9000 ;notre code lui sera en #9000 nolist ;le nolist est une instruction pour l'assembleur et permet de ne pas voir le source défiler à l'assemblage CALL delock ;l'ASIC est delockée ;maintenant on va remplir notre DMA liste avec des int LD HL,#4010 ;#4010 correspond a l'instruction INT pour les DMAlist LD (DMALIST+60),HL ;on place notre instruction INT en #8000+60 octets. LD (DMALIST+80),HL ;une autre int LD (DMALIST+150),HL ;une autre LD (DMALIST+180),HL ;une petite dernière LD HL,#4020 ;instruction STOP LD (DMALIST+200),HL ;Notre DMAlist s’arrêtera ici ;attention c'est là que tout se passe maintenant DI ;on coupe les interruptions car on va les modifier CALL ASICON LD A,1 LD (#6800),A ;on met une interruption raster a la ligne 1 CALL ASICOFF ;on déconnecte la page I/O ASIC pour le moment ;cette interruption raster va nous permettre de lancer la DMAlist... ;on passera en IM 2 pour que tout se gère tout seul ;on va donc faire une routine qui lancera la DMAlist et dans laquelle l'int raster sautera ;voir la sous routine INIT_DMA_LIST ;notre routine sera en #2000 ;on la recopie donc là LD HL,INIT_DMA_LIST ;notre routine est là LD DE,#2000 ;on l'enverra en #2000 LD BC,100 ;elle fait 100 octets de longueur LDIR ;on recopie ;notre routine pour les int raster est prête ;on s'occupe maintenant de celle pour les DMA son LD HL,DMA_INT ;notre routine est la LD DE,#3000 ;on la mettra en #3000 LD BC,83 ;elle fait 60 octet de long LDIR ;on recopie ;maintenant que nos routines sont prêtes, on va donner l'adresse de celle-ci pour chaque DMA. CALL ASICON ;on connecte la page I/O ASIC LD A,#10 ;le poids fort de la table des vecteurs d'interruption LD I,A ;on le met dans I LD A,0 LD (#6805),A ;on met 0 dans IVR. Notre table des vecteurs d'interruption sera donc en #1000 ;les acquittements seront universels car le bit 0 est a 0 LD HL,#3000 ;adresse de notre routine pour le DMA son 1 LD (#1002),HL ;on met cette adresse pour le DMA son 1 LD HL,#2000 ;adresse de notre routine pour le DMA raster LD (#1006),HL ;on met cette adresse pour le DMA raster CALL ASICOFF ;on a termine et on déconnecte la page I/O ASIC IM 2 ;on passe en IM2 EI ;on rétablis les int BOUCLE JP BOUCLE ;boucle sans fin ;*********************************************************************************** ;*************************** ROUTINE POUR L'INT DMA RASTER ************************* ;*********************************************************************************** INIT_DMA_LIST PUSH BC ;on sauvegarde BC et AF car on va s'en servir PUSH AF CALL ASICON LD HL,DMALIST ;Adresse de notre DMA list LD (#6C04),HL ;on donne l'adresse de la DMA list pour le DMA1 LD A,%00000010 ;on va allumer le DMA1 LD (#6C0F),A ;voila qui est fait CALL ASICOFF ;on en profite pour faire un raster bleu LD BC,#7F10 ;sélection du border OUT (C),C LD A,85 ;bleu vif OUT (C),A ;on envois DS 64,0 ;on patiente LD A,84 ;du noir OUT (C),A ;on envois POP AF ;on récupère AF et BC POP BC EI ;on remet les interruptions RET ;*********************************************************************************** ;*************************** ROUTINE POUR L'INT DMA SON ************************ ;*********************************************************************************** DMA_INT PUSH BC ;on sauvegarde BC PUSH AF ;on sauvegarde AF car on va s'en servir LD BC,#7F10 ;sélection du BORDER OUT (C),C LD A,76 ;couleur rouge OUT (C),A ;on envois DS 64,0 ;on ajoute des NOPs histoire que ce soit visible LD A,84 ;du noir OUT (C),A ;on envois POP AF POP BC EI ;on rétablis les interruptions RET ;fin ;***************************************************************************** ;***************************** ROUTINES ANNEXES ****************************** ;***************************************************************************** DELOCK LD HL,TASIC LD D,17 DELOCKK LD BC,#BC00 LD A,(HL) OUT (C),A INC HL DEC D JP NZ,DELOCKK RET TASIC DB 255,0,255,119,179,81,168,212,98,57,156,70,43,21,138,205,238 ASICON LD BC,#7FB8 OUT (C),C ;on connecte la page I/O ASIC RET ASICOFF LD BC,#7FA0 ;on déconnecte la page I/O ASIC OUT (C),C RET
Surtout faites bien attention, la routine se lance en #9000 !!!
Bien entendu, les DMA-list n'ont pas pour fonction première de générer ce genre de chose.
Les int DMA son ont plutôt pour but de vous aider à synchroniser des effets avec la musique par exemple.
Mais c'est un cas assez pratique pour générer des effets sans avoir à s'en occuper, comme par exemple un dégradé grossier en raster ou pour déplacer automatiquement des sprites hard sans avoir recourt à la rupture à coup de CRTC.