9.3. Unités d'entrées/sorties

Les unités d'E/S sont des interfaces entre la mémoire de l'Apple et les périphériques. Dans l'émulateur, c'est une interface entre les couches noyau et matériel.

9.3.1. Classe unité

Les unités sont représentés par des classes descendantes de la classe CUnit.

Du côté mémoire de l'Apple, seules deux méthodes sont utilisées : read (lecture) et write (ecriture). C'est à peu près la même chose que pour une mémoire excepté que l'adressage est en 8 bits au lieu de 16.

Du côté périphérique, il n'y a pas de spécification. La plupart des unités ne comportent que des interrupteurs logiciels. A chaque interrupteur correspoind une méthode get_<switch> et, si modifiable, une méthode set_<switch>, où <switch> est le nom de l'interrupteur en minuscules.

Les unités ont une méthode reset qui est censée remettre à zéro l'unité. Elle est appelée à l'instanciation de l'unité mais aussi lorsque l'utilisateur appuie sur le bouton "reset" (ça c'est dans la couche matériel).

Toutes les unités sont observables et doivent notifier de tout changement pouvant subvenir. Les objets de la couche matériel doivent observer les unités pour être informés de ce qu'il se produit.

9.3.2. Clavier (Keyboard)

Compatibilité : Tous modèles.

Cette unité est en charge du clavier. Sur les Apple II, il n'y avait pas de tampon clavier. Cette unité ne peut donc gérer qu'une touche à la fois.

9.3.2.1. Méthodes

void press_key(BYTE key);

Indique à l'unité quelle touche est en train d'être pressée. Notez que si la touche précédente n'a pas encore été lue, elle sera oubliée. Les codes de touche doivent être en code ASCII Apple.

void release_key();

Indique à l'unité que la touche a été relâchée.

bool key_waiting();

Indique s'il y a une touche en attende de lecture par l'Apple. Cette méthode peut être particulièrement utile pour développer un tampon clavier ou un outil de copier coller.

9.3.2.2. Addresses

AdresseNomAccèsEffet
0x00KBDRBits 0-6 : Dernière touche pressée ou en train de l'être. Bit 7 : est à 1 si une touche a été pressée depuis la dernière remise à zéro.
0x10KBDSTROBERWRemet à zéro le clavier. Bits 0-6 : Dernière touche pressée ou en train de l'être. Bit 7 : à 1 si une touche est enfoncée.

9.3.3. Cassette (Tape)

Compatibilité : Tous modèles.

Malheureusement cette unité n'est pas encore implémentée.

9.3.4. Haut parleur (Speaker)

Compatibilité : Tous modèles.

Le haut parleur de l'Apple est plutôt basique : il n'a que deux niveau. Le niveau du haut parleur est inversé en accédant à l'interrupteur logiciel SPKR. Du côté périphérique, le niveau du haut parleur peut être lu.

9.3.4.1. Interrupteurs

InterrupteurOffOn
SPKRHaut parleur au niveau basHaut parleur au niveau haut

9.3.4.2. Adresses

AdresseNomAccèsEffet
0x30SPKRRWChange l'état de SPKR

9.3.5. Jeu (Game)

Compatibilité : Tous modèles (sauf peut être le //c).

L'unité de jeu possède trois sortes de dispositif : Trois boutons poussoirs, quatre annonciateurs et quatre entrées analogiques.

Les boutons poussoirs sont connectés à ceux du joystick ou des paddles. A partir du //e, le bouton 0 est aussi connecté à la touche du clavier Pomme Ouverte et le bouton 1 à la touche Pomme Pleine. Sur certains modèles de //e, le bouton 2 était connecté à la touche Shift.

Les annonciateurs sont des sorties sur la prise jeu, capable de sortir à deux niveaux (ils n'ont pas été beaucoup utilisé, peut être pas du tout).

Les entrées analogiques sont connectées aux axes X et Y du joystick (habituellement, les entrées 0 et 1) ou aux paddles. Ces entrées analogiques fonctionnaient en mesurant le temps de décharge d'un condensateur dans le potentiomètre du joystick ou de la paddle. L'unité n'est capable que de déclencher la charge du condensateur et de détecter lorsqu'il est déchargé. La mesure de temps est effectuée par un programme en ROM.

Il est important de simuler ce mécanisme car certains programmes implémentent leur propre routine de mesure. La difficulté est qu'il est important de synchroniser le simulateur à l'horloge pour que le décompte de cycles, vu depuis l'intérieur, soit correct.

9.3.5.1. Interrupteurs

InterrupteurOffOn
AN0Annonciateur 0 au niveau basAnnonciateur 0 au niveau haut
AN1Annonciateur 1 au niveau basAnnonciateur 1 au niveau haut
AN2Annonciateur 2 au niveau basAnnonciateur 2 au niveau haut
AN3Annonciateur 3 au niveau basAnnonciateur 3 au niveau haut
PB0Bouton 0 relâchéBouton 0 appuyé
PB1Bouton 1 relâchéBouton 1 appuyé
PB2Bouton 2 relâchéBouton 2 appuyé
PADDL0Condensateur de l'entrée 0 déchargéCondensateur de l'entrée 0 chargé
PADDL1Condensateur de l'entrée 1 déchargéCondensateur de l'entrée 1 chargé
PADDL2Condensateur de l'entrée 2 déchargéCondensateur de l'entrée 2 chargé
PADDL3Condensateur de l'entrée 3 déchargéCondensateur de l'entrée 3 chargé
PTRIGLes condensateurs sont en déchargeLes condensateurs sont en charge

9.3.5.2. Adresses

AdresseNomAccèsEffet
0x58CLRAN0WRÉteint AN0
0x59SETAN0WRAllume AN0
0x5ACLRAN1WRÉteint AN1
0x5BSETAN1WRAllume AN1
0x5CCLRAN2WRÉteint AN2
0x5DSETAN2WRAllume AN2
0x5ECLRAN3WRÉteint AN3
0x5FSETAN3WRAllume AN3
0x61PB0R7Lit l'état de PB0
0x62PB1R7Lit l'état de PB1
0x63PB2R7Lit l'état de PB2
0x64PADDL0R7Lit l'état de PADDL0
0x65PADDL1R7Lit l'état de PADDL1
0x66PADDL2R7Lit l'état de PADDL2
0x67PADDL3R7Lit l'état de PADDL3
0x70PTRIGRDéclenche la charge des condensateurs*

* : Quand la charge est déclenchées, PTRIG passe à vrai, les observateurs sont notifiés, puis il repasse à faux (les observateurs sont de nouveau notifiés). Tout cela dans le même cycle d'horloge (en réalité, pendant le même appel de méthode). C'est la façon dont l'unité de jeu informe les observateurs qu'il doivent commencer la simulation de la décharge.

9.3.6. Mode graphique (GraphicMode)

Compatibilité : Tous modèles.

Réference: Apple IIe Technical Reference Manual page 29 (PDF p63)

Cette unité s'occupe du passage du mode texte aux modes graphiques, excepté le mode double haute résolution qui a été implémenté plus tard. L'Apple ][ a un mode texte et deux modes graphiques (basse et haute résolution). Un mode mixte permet de partager l'écran en deux, en ayant 4 lignes de texte en bas et le reste en graphique. Chaque mode possède deux pages correspondant à deux espaces mémoire différents.

9.3.6.1. Interrupteurs

InterrupteurOffOn
TEXTMode graphiqueMode texte
MIXEDMode plein écranMode mixte
PAGE2Page 1 affichéePage 2 affichée
HIRESBasse résolution Haute résolution

9.3.6.2. Adresses

AdresseNomAccèsEffet
0x50TXTCLRRWPasse TEXT à 0
0x51TXTSETRWPasse TEXT à 1
0x52MIXCLRRWPasse MIXED à 0
0x53MIXSETRWPasse MIXED à 1
0x54TXTPAGE1RWPasse PAGE2 à 0
0x55TXTPAGE2RWPasse PAGE2 à 1
0x56LORESRWPasse HIRES à 0
0x57HIRESRWPasse HIRES à 1

Et, sur le //e et les modèles suivants, quelques adresses de lectures ont été ajoutées :

AdresseNomAccèsEffet
0x1ARDTEXTR7Lit l'état de TEXT
0x1BRDMIXEDR7Lit l'état de MIXED
0x1CRDPAGE2R7Lit l'état de PAGE2
0x1DRDHIRESR7Lit l'état de HIRES

9.3.7. Ports d'extension (Slots)

Compatibilité : Tous modèles.

Cette unité gère les ports d'extension de l'Apple. Elle ne fait que transférer les requêtes de lectures et d'écriture sur l'espace $C090-$C0FF vers l'unité d'entrée/sortie de la carte correspondante.

Comme le Bus des ROM périphériques, cette unité doit être informée quand une carte est insérée ou retirée.

9.3.7.1. Méthodes

void insert_card(int slot, CUnit *cardUnit);

Indique à l'unité qu'une carte a été insérée. slot est le numéro du port (1-7) et cardUnit est l'unité d'E/S de la carte d'extension.

void remove_card(int slot);

Indique à l'unité qu'une carte a été retirée. slot est le numéro du port (1-7).

9.3.7.2. Adresses

AdresseNomAccèsEffet
0x90-0x9F RWTransféré aux adresses 0x00-0x0F de la carte du port 1
0xA0-0xAF RWTransféré aux adresses 0x00-0x0F de la carte du port 2
0xB0-0xBF RWTransféré aux adresses 0x00-0x0F de la carte du port 3
0xC0-0xCF RWTransféré aux adresses 0x00-0x0F de la carte du port 4
0xD0-0xDF RWTransféré aux adresses 0x00-0x0F de la carte du port 5
0xE0-0xEF RWTransféré aux adresses 0x00-0x0F de la carte du port 6
0xF0-0xFF RWTransféré aux adresses 0x00-0x0F de la carte du port 7

9.3.8. Carte langage (Language Card)

Compatibilité : Tous modèles (probablement sauf le ][).

Réference : Apple IIe Technical Reference Manual pages 79 à 83 (PDF pp113-117)

Cette unité pilote le Bus de la carte langage en utilisant trois interrupteurs : LCRAM, LCBNK2 et LCWRITE.

Seuls LCRAM et LCBNK2 peuvent être lus depuis l'intérieur de l'Apple. LCWRITE n'est pas le nom officiel pour cet interrupteur (j'ai choisis celui là car je n'ai pas trouvé d'autre nom dans la documentation).

Pour changer l'état de LCWRITE, deux requêtes de lectures doivent être effectuées à l'adresse appropriée. Un quatrième interrupteur est utilisé dans Vinace pour gérer cette double lecture. Il est appelé LCWCHG.

9.3.8.1. Interrupteurs

InterrupteurOffOn
LCBNK2Page 2 RAM utilisée en $D000-$DFFFPage 1 RAM utilisée en $D000-$DFFF
LCRAMROM lue en $D000-$FFFFRAM lue en $D000-$DFFF
LCWRITEPas d'écriture en $D000-$FFFFÉcriture en RAM en $D000-$FFFF (même si elle n'est pas visible)

9.3.8.2. Adresses

AdresseNomAccèsEffet
0x11RDLCBNK2R7Lit l'état de LCBNK2
0x12RDLCRAMR7Lit l'état de LCRAM
0x81 RPasse LCBNK2 à 1, LCRAM à 1 et LCWRITE à 0
0x81 RRPasse LCBNK2 à 1, LCRAM à 0 et LCWRITE à 1
0x82 RPasse LCBNK2 à 1, LCRAM à 0 et LCWRITE à 0
0x83 RRPasse LCBNK2 à 1, LCRAM à 1 et LCWRITE à 1
0x84-0x87  Identique à 0x80-0x83
0x88 RPasseLCBNK2 à 0, LCRAM à 1 et LCWRITE à 0
0x89 RRPasse LCBNK2 à 0, LCRAM à 0 et LCWRITE à 1
0x8A RPasse LCBNK2 à 0, LCRAM à 0 et LCWRITE à 0
0x8B RRPasse LCBNK2 à 0, LCRAM à 1 et LCWRITE à 1
0x8C-0x8F  Identique à 0x88-0x8B

9.3.9. Mémoire auxiliaire (Aux Memory)

Compatibilité: //e et suivants.

Malheureusement cette unité n'est pas encore implémentée.

9.3.10. Mode texte (Text Mode)

Compatibilité: //e et suivants.

Cette unité s'occupe du passage entre les modes 40 et 80 colonnes, ainsi que du changement de police de caractère.

9.3.10.1. Interrupteurs

InterrupteurOffOn
80VIDAffichage 40 colonnesAffichage 80 colonnes
ALTCHARUtilisation de la police primaireUtilisation de la police alternative

9.3.10.2. Adresses

AdresseNomAccèsEffet
0x0CCLR80VIDWPasse 80VID à 0
0x0DSET80VIDWPasse 80VID à 1
0x0ECLRALTCHARWPasse ALTCHAR à 0
0x0FSETALTCHARWPasse ALTCHAR à 1
0x1ERDALTCHARR7Lit l'état de ALTCHAR
0x1FRD80VIDR7Lit l'état de 80VID

9.3.11. Rom E/S (I/O Rom)

Compatibilité : //e, IIgs

Certains modèles d'Apple avaient plus de 12Ko de ROM. Pour accéder aux reste de la ROM, l'espace mémoire $C100-$CFFF, habituellement réservé aux ROMs des périphériques, pouvait être utilisé. Une fenêtre en $C300-$C3FF, correspondant à la carte 80 colonne, pouvait être sélectionnée spécifiquement.

Cette unité pilote le Bus de la ROM E/S qui s'occupe de la commutation entre la ROM interne et la ROM des périphériques en $C100-$CFFF.

9.3.11.1. Interrupteurs

InterrupteurOffOn
CXROMROM périphériques en $C100-$CFFFROM interne en $C100-$CFFF
C3ROMROM sélectionnée par CXROM en $C300-$C3FFROM interne en $C300-$C3FF

9.3.11.2. Adresses

AdresseNomAccèsEffet
0x06SETSLOTCXROMWPasse CXROM à 0
0x07SETINTCXROMWPasse CXROM à 1
0x0ASETINTC3ROMWPasse C3ROM à 0
0x0BSETSLOTC3ROMWPasse C3ROM à 1
0x15RDCXROMR7Lit l'état de CXROM
0x17RDC3ROMR7Lit l'état de C3ROM