CODINGAMSLIVE ★ AMSLIVE n°16 - LES GROS PORTS ★

AMSLIVE n°16 - les Gros PortsCoding Amslive

Cet article était à la base prévu pour un AFC Hors série numéro dos, mais Roudoudou se retrouva trop occupé pour le réaliser. Alors Amslive se farcit la garde du petit. (NDSNN : C'est de moi qu'tu parles ? )

Si la tâche essentielle du Z80 consiste à manipuler ses registres et le contenu des RAM et ROM, il doit pouvoir aussi converser avec d'autres circuits, s'occupant eux de tâches plus spécifiques. Ce sont les opérations d'entrée-sortie (IO pour INput OUTput).

Les données transitent sur le bus de données, qui est le même que pour l'accès à la mémoire. Pour éviter toute confusion, lors d'une IO (c'est soit I soit 0 !), le signal MREQ* (Memory REQuest) est haut et IORQ* est bas (* : signaux actifs à l'état bas). Un seul de ces signais suffirait pour départager Mémoire/Périphérique, mais y'a quand même les deux parce qu'ils servent à d'autres choses.

RD* (read) et WR* (write) précisent le sens de NO.

Ceci ne suffit pas pour savoir quel périphérique est adressé. Lors d'une IO, le Z80 place le registre C sur les 8 bits de poids faible du bus d'adresses. Notre CPU ne faisant pas les choses à moitié, B est placé sur les 8 bits de poids fort. Mais comme B évolue en tant que compteur avec certaines instructions IO, il n'est à PRIORI pas utilisable pour l'adressage, il se trouve juste là "par hasard".

-> TOUT CECI EXPLIQUE POURQUOI LES INSTRUCTIONS S'APPELLENT OUT (C),r.

256 périphériques différents s'avéreraient donc adressables si le décodage d'adresse portait sur les 8 bits à chaque fois. Mais ceci est électroniquement assez lourd ; les ingénieurs AMSTRAD ont joué l'économie en simplifiant à l'extrême le décodage. De plus les malheureux ont commencé par exploiter les bits de poids fort (ceux de B, qu'on était censé pas toucher), nous empêchant ainsi d'exploiter les instructions IO bouclantes.
Voici comment les périphériques CPC sont adressés :

— GATE ARRAY (en tant que périphérique et non pas en tant que gestionnaire transparent de la mémoire) :A15 = 0, A14 = 1, RD* = 1 (Et voilà pourquoi A15 et A14 ont été choisis : ils servent aussi au GA pour savoir quelle mémoire sélectionner suivant les ROMS et les RAMS connectées, car dans le cas d'une adresse mémoire, A15 et A14 déterminent la page).
La condition RD* = 1 (état inactif) implique qu'en cas de lecture, le Gâte Array ne réagit absolument pas. Le bus de données reste à l'état haute impédance (comme avec un INP(&FFxx) puisqu'aucun périphérique ne force les bits), et la valeur lue par le Z8Q n'en a aucune (valeur, ouarff !). Mais il semble que ça soit tout le temps &FF sur CPC et &7A sur CPC+ (quand il n'y a aucun périphérique externe de branché -Vidi, Scanner Dart...).

- CRTC :A14 = 0,
A9 / A8
0 0 : sélection du registre CRTC
0 1 : écriture données.
1 0 : lecture registre d'état (cf article CRTC)
1 1 : lecture donnée

Remarque : cette fois, ce ne sont pas RD* et WR* qui déterminent le sens de lecture (ils ne sont même pas reliés au CRTC). Ce qui veut dire que l'on peut faire une opération IO contradictoire : demander une lecture avec un OUT et une écriture avec un IN.

Le deuxième cas de figure n'occasionne aucun problème, simplement &FF (ou &7a, cf plus haut) est envoyé au périphérique.

Par contre, la 1ère peut provoquer un conflit : le Z80 et le périphérique vont tous les deux forcer les bits du bus à des états éventuellement différents.

  • Sélection du numéro de ROM haute : A13 = 0.
  • IMPRIMANTE : AI 2 à 0, en combinaison avec WR*, place la donnée sur le port (physique) à travers la bascule 74LS273.
  • PPI : A11 = 0, A8 et A9 déterminent le port du PPI (A, B ou C) ou le registre de contrôle.
  • µPD : A10 = 0, A8 = 1, A7 = 0, A0 = 0 Registre d'état (en entrée), A0 = 1 Registre de données.
    mais pourquoi sur terre A7 a été choisi plutôt que A9 comme avec le CRTC ou le PPI?
  • Commande MOTEUR : A10 = 0, A8 = 0, A7 = 0.

POURQUOI 7FXX, BCXX, etc ... ?

Ces adresses correspondent à la sélection d'un unique périphérique (ex GA : bit A15 = 0, tous les autres à 1 ).

Le décodage sommaire rend possible l'adressage simultané de plusieurs périphériques. Par exemple OUT &B4xx,0 sélectionne le registre 0 du CRTC et envoie 0 sur le PPI (port A), car A14 = 0, A11 =0. Par contre, impossible d'adresser le GA et le CRTC en même temps.

Ce multi-adressage gêne plus souvent qu'il n'est utile ! Nombreux programmeurs se sont cassés les dents avec l'instruction OUT (n),A (voir un peu plus loin) ; ainsi, dans le Protracker de Crown, lorsqu'on joue un module sur le PSG (choix par défaut) mais qu'on branche une soundplayer, on se rend bien compte que pleins de données incongrues se retrouvent sur le port imprimante.

Ou alors certains, pour une raison différente, allumaient involontairement la led du lecteur 3" en faisant des rasters (n'est-ce pas Tom&jerry ?).

Dernière remarque, LA LECTURE DE PLUSIEURS PERIPHERIQUES EN MEME TEMPS N'EST PAS REMBOURSEE PAR LA SECURITE SOCIALE.

QUELLES ADRESSES VALABLES ?

Tant que A10 = 1, le poids faible (registre C) n'influe pas, ce qui justifie l'écriture &7Fxx par exemple (xx représentant une valeur quelconque). Soulignons de la même façon que A8 et A9 n'importent pas tant que A10, A11 et A14 restent à 1. Le GA peut donc aussi être sélectionné par 7Exx, 7Dxx, 7Cxx (attention, l'extension 2Mo de RAM7 détecte cela et commute alors différentes pages).

Allons plus loin : ni le FDC ni le moteur ne risque de se voir sélectionné si A7 = 1. On peut alors mettre A10 à 0, ce

qui offre de nouveaux poids fort pour adresser le GA : 7B, 7 A, 79 ou 78.

Pour le CRTC, on peut mettre A15 = 0 et A14 = 0. Si on veut A10 = 0, on fixe A7 à 1 sans pour autant immobiliser le registre C : si on s'en sert pour une sélection de registre, cela ne pose pas de problème, car celle-ci se fait sur 5 bits (OC équivaut à 2C, 4C, 6C, etc). Et tous les registres CRTC ne sont pas 8 bits.

LE CAS OUT (nn).A

Cette instruction est remarquable : elle tient en 1 octet, ne dure que l'équivalent de 3 NOPs (ceci expliquant cela...), et il s'agit de la seule à ne pas mettre BC sur le port d'adresse mais An.

Puisque A sert à la fois de donnée et de poids fort d'adresse, toutes les combinaisons ne sont pas exploitables. Par exemple : A = 0 sélectionnera le reg 0 du CRTC, enverra 0 sur le port imprimante,
0 sur le port A du PPI et éteindra le moteur pour peu que le bit 7 de nn soit à 0.

Mais d'autres cas sont plus arrangeants : bit 7 de nn à 1, toute donnée vérifiant :
bit 0 à 1, bit 1 à 0, bit 3 à 1, bit 4 à 1 (soit 16 valeurs bien précises) peut être envoyée au CRTC sans adresser d'autres ports.
A vous d'analyser cas par cas les périphériques adressés et la valeur qui leur est envoyée.

IN A,(nn)

Ici, ça marche parfaitement : on fixe le poids fort du port dans A, qui est ensuite écrasé par la valeur lue.

LE Z80 NE LAISSE PAS TON B

INIR, INDR sont à proscrire définitivement. OTIR et OTDR ne sont pas utilisables, ne serait-ce que parce que les 16 dernières valeurs envoyées le seraient aussi au port imprimante : pitié pour les possesseurs de SOUNDPLAYER.

Par contre, pas de problème avec INI, OUTI, IND, OUTD, tant qu'on oublie pas"de remettre B à jour. Remarque importante, il est décrémenté AVANT l'opération IO. Avec le GA, peu l'avaient remarqué puisque, comme on l'a vu, #7Exx convient aussi. Ca permet d'ailleurs une petite optimisation (cadeau du laboratoire Overlanders !) qui ressemblerait à :

LD BC,#8080 ; là réside l'astuce : bit 7 à 1 !
LD HL,TABLE_GA
;
OUTI : OUTI : OUTI : OUTI : OUTI : OUTI :
OUTI : OUTI
LD B,C
OUTI : OUTI : OUTI : OUTI : OUTI : OUTI :
OUTI : OUTI

INSTRUCTIONS BONUS

  • ED 70 : IN F,(C) Met à jour le registre F suivant la valeur lue. Si 0 par ex, alors le flag Z est mis. Comme avec IN A,(C), en fait, sauf que ça ne modifie pas A !
  • ED 71 : OUT (C),0 Explicite !

Voilà, tout cet article concerne le CPC nu. Pour l'adressage des différents périphériques existant sur CPC, FutureSoft a établit une liste assez complète, que l'on dégotera par exemple page 32 du magazine "Le chasseur français".

OUT &Madram, comment ça va ? , AMSLIVE n°16

★ ANNÉE: ???
★ AUTEUR: MADRAM

Page précédente : AMSLIVE n°16 - CRTC Detection

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding » AMSLIVE n°14 - Multiplication Saignee a Mort
» Coding » AMSLIVE n°15 - la Vie en 16
» Coding » AMSLIVE n°15 - CPC Sos Partie 3
» Coding » AMSLIVE n°12 - Rom Pour les Matelots
» Coding » AMSLIVE : La rubriques programmation
» Coding » AMSLIVE n°04 - Z80
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop/c
Page créée en 248 millisecondes et consultée 2212 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.