★ CODING ★ Les derniers mysteres ★ |
LOGON CPCPLUS 47: Les derniers mystères |
Oui, je sais ! Il n'y a pas eu d'article sur le CPC Plus dans le numéro précédent, mais c'est la faute de Pict qui a pris toute la place. Hmmm, après cette explication fumeuse, venons-en directement au sujet de la prose de ce mois. Cet article met enfin un terme à la description de tous les registres « secrets » du CPC Plus. Je vais donc aborder:
LES INTERRUPTIONS! Argh! Nous avons déjà abordé le chapitre des interruptions dans la rubrique Logon (cf. Amstrad CPC n033, p. 50)et Digit vous avait preque tout expliqué. Pour reprendre, une interruption est le nom donné à une action (le plus souvent un branchement) effectuée par le microprocesseur (en l'occurrence le Z80A). Celui ci interrompt l'exécution séquentielle des instructions pour simuler un appel à une routine (un CALL en Z80A si vous préférez). Deux questions se posent dès lors. Qui dit au micro-processeur qu'il va devoir « interrompre » le programme en cours? A quelle adresse le Z80A va-t-il? A cette question... il y a plusieurs réponses. Ben pourquoi donc? Parce qu'il y a plusieurs type d'interruptions sur Z80A. Les "ordinaires" (modes IM0, IM1 et IM2), les demandes de Bus (BUSRQ) et les interruptions non masquables (NMI). Je signale au passage que je parlerai ici uniquement des interruptions ordinaires, mais sachez néanmoins que la NMI est générée par le bouton poussoir de votre multiface 2 (le vecteur de cette interruption se trouvant en #0066). Le mode IM0 est un mode ou le périphérique insère ses propres instructions sur le bus de données et ne nous intéresse pas, car il n'est jamais utilisé. Le mode IM1 correspond à un mode non vectorisé. Le mode IM2 à un mode vectorisé des interruptions. La vectorisation permet d'attribuer à chaque périphérique (souvenez-vous, c'est un déclencheur d'interruption) sa propre adresse. En mode non vectorisé, le Z80A appelle une adresse précise (située en #0038) et la routine située à cet endroit doit alors tester quel périphérique l'a appelée. Sur le CPC+ en mode « old generation », seul le Gate Arrray émulé « génère » des interruptions. Le Gate Array étant la seule source d'interruption, il n'y a pas besoin de l'identifier. Sur un CPC "ancienne génération" (ou CPC+ dans ce mode) le mode vectorisé IM2 n'a donc pas d'utilité pour identifier la source de l'interruption mais ce mode peut en revanche permettre le changement de l'adresse « immuable » #0038 pour les interruptions (certains programmes pouvant avoir besoin de libérer cette zone...). Mais un bug du mode IM2 sur les CPC "ancienne génération" oblige à dépenser 257 octets de Ram pour pouvoir déplacer l'adresse d'interruption. VECTORISER EN MODE IM2 Pour vectoriser en mode IM2 il faut utiliser une table de vecteurs (entendez « adresse d'interruption » pour « vecteurs). Ainsi, dans une table se suivent des adresses de routines d'interruption. Comment définir l'adresse de la table d'interruption? a) L'octet de poids fort de l'adresse de la table est défini par le registre I du Z80A (mais si, mais si, il servait à quelque chose !). b) L'octet de poids faible de l'adresse est normalement fourni par le périphérique qui génère l'interruption. Le problème sur les vieux CPC est que le périphérique n'a pas de numéro et les 7 bits de poids fort de cette valeur sont aléatoires (en outre, le bit 0 est souvent à 1 sur les « old » et toujours à 0 sur le CPC+, d'où une incompatibilité du mode IM2 entre les 2 machines lorsque le Plus fonctionne en mode "Old"!).C'est pourquoi, pour utiliser le mode IM2 sur un Cpc "Old" (ou Plus en mode "Old"), l'astuce consiste à utiliser un vecteur qui soit le même quelque soit l'adresse pointée dans la page de 257 octets pointée par Ix256. Il faut donc que le vecteur soit une adresse dont le poids fort est égal au poids faible, par exemple #3232, et recopier 257 fois la valeur #32 (pour l'exemple) pour utiliser le mode IM2.
Le schéma n°1 décrit l'adresse de la table des vecteurs sur CPC+. L'octet situé en #6805 Asic (IVR) permet de définir, avec le registre I, les bits 3 à 15 de l'adresse de la table. Lorsqu'une interruption à lieu, les bits 1 & 2 sont positionnés par le périphérique qui génère l'interruption, d'où branchement à une adresse spécifique. Notons au passage que le bit 0 de l'adresse vaut toujours 0 et implique que la table commence sur une adresse paire. La grande précision au niveau de l'adresse apportée par le registre IVR permet de ne « dépenser » que 8 octets pour la table d'interruption. En mode IM1, nous avons vu que les interruptions ont toutes lieu en #0038. La routine située à cette adresse doit donc être capable de savoir quelle était l'interruption générée par l'Asic. Pour cela, il existe un registre de statuts dans l'Asic, qui permet de savoir quelle interruption a eu lieu. Vous connaissez déjà ce registre, appelé DCSR, car je l'avais décrit dans le n°45, page 39, schéma 3. Le revoici sur le schéma n°2.
Que l'interruption ait bien lieu est une chose, mais il faut savoir dire qu'elle est finie pour qu'une nouvelle puisse « arriver ». On appelle cette action un acquittement d'interruption. D'ordinaire, un simple EI suffit à informer le Z80A qu'il pourra accepter une nouvelle interruption. Sur le CPC+, plusieurs méthodes s'offrent à nous. Le tableau du schéma n°3 décrit tous les acquittements possibles. Signalons au passage que le bit 0 du registre IVR, placé à 0, permet d'utiliser EI comme instruction d'acquittement automatique non spécifique à une interruption (ceci pour les DMA puisque l'interruption raster est toujours acquittée automatiquement). Ceci a été fait pour faciliter les acquittements en mode vectorisé (IM2), puisque chaque interruption a sa routine propre. L'inconvénient de ce procédé (bit 0 de IVR à 0) en mode IM1 est que les bits 4 à 7 de DCSR ne sont plus mis à jour (ou du moins testables), et la routine ne peut donc pas savoir quelle interruption a eu lieu. POUR RESUMER En mode IM2, vous savez implicitement quelle interruption a lieu et vous pouvez vous contenter d'acquitter vos interruptions par EI en plaçant le bit 0 de IVR à 0.
Sachez néanmoins que la valeur du bit 0 de IVR au reset est 1 LES DIFFERENTES INTERRUPTIONS L' interruption Raster permet de déclencher une interruption à une ligne spécifiée à l'adresse #6800 (PRI). Il est possible de reprogrammer cette interruption pour générer plusieurs interruptions durant le balayage. Notons que la ligne prise en compte est la première ligne de données affichées et non pas la première ligne du balayage ! Ceci peut être gênant pour avoir des interruptions « en dehors de l'espace d'affichage programmé avec le CRTC lorsqu'on augmente les lignes définies par le basic (200)». Lorsque le contenu de #6800 est différent de 0, alors l'interruption raster remplace l'ancien système d'interruptions émulé. Il existe par ailleurs un bug hardware avec le mode vectorisé du CPC+. Si le bit 13 de l'adresse de l'instruction interrompue est égal à 0, alors l'interruption DMA 0 est appelée en lieu et place de l'interruption Raster dans certaines situations, selon la nature de l'instruction interrompue (dans le contexte ou le bit 13 de son adresse=0). Autrement dit, pour éviter cette erreur, il faut prévoir de loger le code "interruptible" sur les plages d'adresse ou A13=1, ou encore traiter le vecteur Raster et DMA-0 comme un seul vecteur. LES INTERRUPTIONS DMA-SONS Hem ! Celles-ci sont générées via les AY-Listes que je vous ai décrites dans le n°45, pages 38-40. Voilà, fini le tour d'horizon des interruptions du CPC+ ! Pfewww! LA RUPTURE Passons maintenant à la rupture sur le CPC+. Cette technique, superbidouillage des anciens CPC, est maintenant prévue d'origine dans les entrailles de Asic (qui émule le CRTC !). Il suffit juste de spécifier le numéro de ligne et l'adresse du nouvel écran! Ainsi (#6801 ou Reg SPLT) contient le numéro de la ligne de rupture. Et (#6802, #6803 ou Reg SSA) contient l'adresse du second écran (le premier étant défini par les classiques registres 12 et 13 du CRTC émulé). Tout comme pour l'interruption raster, le numéro de ligne varie entre 1 et 255 ( 0 pour annuler le « split » ) et commence à partir de la première ligne de données affichées. Ceci pose donc problème pour faire du "fullscreen" car un écran peut afficher plus de 256 lignes en hauteur. Après ce bref interlude dans le merveilleux monde de la rupture, passons à la prise située sous l'interrupteur (mais si, elle sert à quelquechose !). LA PRISE ANALOGIQUE Cette prise est donc une entrée analogique composée d'un « convertisseur analogique/digital octal en conjonction avec un réseau R-2R, un comparateur et un multiplexeur analogique ». Burp...A vos souhaits A quoi ça sert? A beaucoup de choses, mais, entre autres, à brancher 4 paddles, 2 joysticks analogiques, etc. On aurait pu penser au son si la vitesse d'échantillonnage avait été autre. Un paddle est en quelque sorte, un potentiomètre permettant de déplacer unidirectionnellement la raquette de votre casse-briques, par exemple. Quant à définir un joystick analogique par rapport à un joystick digital, disons que c'est un joystick « mou » (Poum est un spécialiste de la chose [NDPoum Longshot l'a testé pour vous]) disposant d'une très haute précision et équipé de deux poussoirs (et pas de malentendus). L'Asic dispose de 8 canaux d'entrée analogique, mais seulement 4 parmi eux sont reliés à la prise physiquement (no comment sur le gaspillage). Bref, 8 registres existent dont 4 sont lisibles. Ces registres sont des registres 6 bits mis à jour 200 fois par seconde et traduisent des variations de 0 volt (valeur #00) à 2,5 volts (valeur #3F). Notez que l'impédance en entrée doit être de 1 kilo-ohm. Cependant, chers lecteurs, la doc technique Amstrad, largement incomplète, ne précise pas où les boutons « Fire » sont gérés. Je suppose donc, n'ayant pu le tester à ce jour, que le bit 6 de chaque registre contient l'état du Fire (ou du moins un état fourni sur les broches correspondantes aux Fires).
ET L'IMPRIMANTE? Et pour finir en beauté, si nous parlions de l'imprimante. Pour lui envoyer un octet il suffit de lui demander si elle est prête, ceci via le bit 6 du port B du PPI situé en #F500 (cf. n043, pages 23 à 27). Notons que le système arrive à faire la différence entre un buffer plein et un autre type d'erreur lorsque le bit de contrôle reste trop longtemps à l'état 1. Jusqu'à maintenant le fonctionnement de l'imprimante me paraissait simple. Il suffisait pour lui envoyer un octet d'utiliser le port #EF00 en envoyant 3 fois la valeur (1e: Bit 7=0; 2e: Bit7=1; 3e: Bit7=0), le bit 7 servant à valider l'octet! Pour cette raison, seuls les 7 bits de poids faibles étaient pris en compte. C'est toujours le cas sur ce port pour des raisons de compatibilité! Mais alors ? Où est le 8e bit manquant? (NDLR : Oui, où ?). Accrochez-vous. Celui-ci se trouve sur le bit 3 du registre 12 du CRTC 6845 émulé ( cf n°38, page 48 ). Comme quoi, il n'y a pas de petites économies, puisque ce bit « semblait » inoccupé pour les techniciens d'Amstrad. Ceux-ci ne connaissaient malheureusement pas les Overscan Bits. Dans le cas d'un logiciel "full screen" faisant des impressions, le buffer vidéo fera la valse entre 16 K et 32 K sans arrêt (très psychédélique). Heureusement toutefois que la rupture est là! Bref, pour envoyer un octet 8 bits à l'imprimante, voici quelques lignes de basic que vous adapterez sans problème en assembleur si vous souhaitez modifier les vecteurs systèmes du firmware. 10000 REM B Contient le caractère (0 à 255) |
Page précédente : LOGON CPCPLUS 45: Le CPC plus en musique |
|