CODING ★ GESTION DU CLAVIER SOUS INTERRUPTION ★

Keyboard - Gestion du Clavier Sous Interruption (SOS Programmeurs)

Les routines système du CPC concernant le clavier utilisent abondamment les cycles d'interruption . Pour cette raison : Tout appel à #BB06 , #BB1E , Etc ... A l'intérieur d'une interruption programmée ne peut qu'entraîner un plantage spectaculaire !

Une solution consiste à réécrire une routine de lecture directe du clavier et à convertir les codes lus en numéro de touche ( KEY(N) ) en Basic.

Commençons par le commencement : La lecture directe du clavier .

Seules des instructions IN/OUT peuvent réaliser cette lecture . Comme on ne peut adresser que 8 bits à la fois , le clavier de 80 touches est divisé en 10 lignes de 8 touches chacune (Joystick compris) .

Le clavier est lu par un circuit d'interface nommé PPI . Ce circuit d'interface parallèle est composé de 3 ports de 8 bits : A , B & C .
Le PPI s'occupe de l'interface K7 , du générateur sonore , du signal busy de l'imprimante , des cycles d'interruption et pour la partie qui nous intéresse , du clavier .

Nous n'entrerons pas ici dans le détail de l'électronique Amstrad . Onnotera toutefois que pour économiser de la mémoire , l'adressage de lecture clavier se fait par l'intermédiaire du P.S.G. En fonction de cela, certaines erreurs de programmation ont des effets curieux sur l'instruction SOUND .
L'efficacité primant avant tout , le plus simple est de reproduire en RAM la section 'SCAN KEYBOARD' de la ROM (En #846 pour CPC 464) et de l'adapter à nos besoins .

STRUCTURE DU CLAVIER ET POSITION DES TOUCHES

Voici ci-dessous la répartition des touches sur les 10 lignes du clavier.

F.=Flèche - J.=Joystick - Pn.=Pavé numérique
Colonne=>01234567
Lignes
0F.HauF.DroF.BasPn. 9Pn. 6Pn. 3Pn.EnPn. .
1F.GauCopyPn. 7Pn. 8Pn. 5Pn. 1Pn. 2Pn. 0
2CLR"["Enter"]"Pn. 4SHIFT"ç"CTRL
3"""=""à""P""+""*""?"">"
4"0""9""O""I""L""K""M""<"
5"8""7""U""Y""H""J""N"SPACE
6"6""5""R""T""G""F""B""V"
7"4""3""E""W""S""D""C""X"
8"1""2"ESC"Q"TAB"A"CAPSL"Z"
9J.hauJ.basJ.gauJ.droJ.fir------------DEL

Si ceci vous fait penser à une matrice du genre DIM touches (8,10) vous avez raison ! La touche située sur la ligne 0 colonne 0 est KEY(0) , celle située sur la ligne 2 colonne 8 est KEY (66) , Etc ... Pour trouver le numéro de touche exact : TOUCHE=LIGNE*8 + COLONNE .

La routine assembleur lira successivement chaque ligne du clavier et récupèrera au passage un octet indiquant l'état de cette ligne . Si cet octet contient #FF (11111111) , aucune touche des 8 de la ligne n'est enfoncée . Si une touche est pressée , un des bits de l'octet transmis sera à zéro . La position de ce bit nous donnera la colonne ou se trouve la touche .

Exemples : 11110111 = 3 ème colonne . 10111111 = 7ème colonne . C'est une série de rotations à droite de l'octet qui donnera le numéro de colonne .(Noter que du point de vue binaire , le tableau ci-dessus est a l'envers de gauche à droite) .

Chaque octet lu sera stocké dans un buffer de 10 octets pour interprétation ultérieure . Le principe de base sera :

Lire les 10 lignes du clavier et stocker chaque octet . Ensuite :

;
LD HL,BUFFER DE 10 OCTETS
LD B,10 ;Pour 10 lignes .
LD C,0 ;Contiendra le numéro de touche KEY(n) en sortie .
;
BCL LD A,#FF
CP (HL) ;Si contenu de HL <> #FF on a trouvé une touche pressée .
JR NZ,TOUCHE
;
INC HL ;Aucune touche sur la ligne N .
LD A,8 ;On ajoute 8 touches au compteur C .
ADD A,C ;et on continue .
LD C,A
DJNZ BCL
RET ;Si on sort ici , aucune des 80 touches n'était pressée .
;
TOUCHE LD A,(HL) ;Une touche a été pressée , chercher son numéro .
LOOK RRC A ;Chercher le bit a zéro .
JR NC,TOUCHETROUVEE
INC C ;C contient déja le numéro de ligne , on avance de 1
JR LOOK ;dans la colonne .
;
TOUCHETROUVEE : C'est fini .
;

Comme on le voit , le principe est des plus simples si l'on veut lire une seule touche . Mais il ne faut pas oublier les combinaisons suivantes !

Touche + CTRL , Touche + SHIFT , Touche + SHIFT + CTRL .

Aie aie ... Lire 2 touches sur 2 lignes différentes ne constitue pas unvraiment un problème , on testera en priorité la ligne 2 et mettrons un flag si on y trouve SHIFT ou CTRL , mais SHIFT + CTRL + ENTER = 3 touches sur la même ligne ! Ca ce n'est pas un cadeau ... Dans ce cas le clavier renvoie un code btard qui équivaut à : La touche pressée , AND le code des autres touches pressées . Donc :

ENTER + SHIFT = &FB AND &20 = &DB
ENTER + CTRL = &FB AND & 80 = &7B
ENTER + CTRL + SHIFT = &FB AND &80 AND &20 = &5B

Ou encore &FB AND &A0 =&5B

Dans le cas ou toutes les touches d'une même ligne serait pressées simultanément (Pas facile ça...) , le clavier renvérait donc un 0 . Si la les 80 touches étaient enfoncées (il faut être trois pour y-arriver) , les 10 octets transmis seraient tous à 0 . On peut donc tester simultanément des dizaines de touches à condition de savoir décoder le résultat . (10110101 signifie que les touches des colonnes 6,3 & 1 sont enfoncées sur une même ligne) .

Inutile d'aller aussi loin dans nos spéculations . La reconnaissance de CTRL - SHIFT suffira . J'ai effectué ce décodage de manière un peu particulière . L'octet de ligne 3 est lu en premier . Si il est à #FF nous n'avons ni CTRL ni SHIFT et tout va bien . Sinon un OR &A0 restaure un octet sans SHIFT ni CTRL qui est remis dans le buffer . Ceci est nécéssaire pour que la boucle de décodage ne soit pas perturbée par un octet parasite .

Ceci fait , l'état éventuel de SHIFT - CTRL est stocké et on relit la totalité du buffer pour trouver le numéro de touche .

Un dernier détail : Lorsque SHIFT & CTRL sont enfoncés , la dernière colonne passe de #7F à #5F . Ceci quelque soit la ligne clavier concernée .

La démonstration fournie (Décodage clavier) , vous montrera les résultats obtenus . Notez que si l'état de CTRL - SHIFT est lu et affiché en bas d'écran , on ne le voit pas dans l'affichage du buffer puisque le programme à effacé ces codes du buffer après interprétation . Le Basic est un peu lent . Attendez le BIP avant de relacher les touches . Appuyer sur CTRL+SHIFT+ESC pour quitter ce programme (Le RESET est déconnecté) .

Ci-dessous le listing assembleur de "-KEY-ES" (Voir aussi NOTE après le listing ) .

;
;- LECTURE DU CLAVIER PAR PORTS E/S DU PPI -
;
ORG 40000
;
scankeyboard:
DI ;Toujours interdire les interruptions avant
PUSH HL ;d'utiliser les ports ES
PUSH BC
PUSH AF
****************************** VOIR NOTE **********************************
;
;- Routine recopiée de puis les ROMS -
;
LD BC,#F40E ; Le registre R14 du PSG est connecte au port
OUT (C),C ;A du PPI .
LD B,#F6 ;Envoyer #C0 (11000000) sur le port C du PPI pour
IN A,(C) ;l'activer en mode adressage
AND #30
LD C,A
OR #C0
OUT (C),A ;STROBE on puis OFF . On ne voit pas bien a quoi
OUT (C),C ;ca sert ????
INC B ;Passer sur le port #F7 et envoyer un octet
LD A,#92 ;10010010 qui active le PPI comme suit :
OUT (C),A ;Port A = IN , port B = IN , port C = OUT
LD C,#40 ;01000000 envoyer le bit 6 sur le port C pour activer
PUSH BC ;le mode lecture PPI clavier . Les 4 bits de poids faible
;donnent le numéro de ligne a lire .
;
;- Modifiée a partir d'ici -
;
LD HL,buf1 ;Départ du buffer pour les 10 lignes
bcl : LD B,#F6 ;Envoyer l'ordre de lecture .
OUT (C),C
LD B,#F4 ;Lire le registre R14 sur le port A qui nous donne
IN A,(C) ;l'octet transmis par le clavier . (#FF si aucune
LD (HL),A ;touche enfoncée) .
INC HL ;Adresse stockage ligne suivante .
INC C ;Incrémenter pour lire la ligne clavier suivante .
LD A,C
AND #F ;Tester si on atteint la 10eme ligne
CP 10
JR NZ,bcl ;Sinon recommencer
;
POP BC ;Restaurer l'état des ports E/S
LD A,#82 ;Sinon Gare !!
OUT (C),A ;(Copie depuis ROMS)
DEC B
OUT (C),C
POP AF ;Si cette routine est utilisée sous interruption
POP BC ;Placer un RET après EI et n'appeler la routine de
POP HL ;décodage que quand c'est nécéssaire .
EI
***************************************************************************
;
; - Routine de décodage .
;
keydecod:
XOR A ;RAZ de la case CTRL-SHIFT
LD (statkey),A
DEC A ;Et mise a #FF du numéro de touche
LD (numkey),A
;
LD A,(buf1+2) ;Tester d'abord la ligne maudite (3)
CP #FF ;Si #FF aucune touche de cette ligne
JR Z,nostats
;
LD HL,bitmap ;Charger adresse table pour comparaison .
LD B,5 ;Voir les 5 1ers octets et éliminer les cases
bclmap:
CP (HL) ; <> SHIFT ou CTRL
JR Z,nostats
INC HL
DJNZ bclmap
INC HL ;Sauter aussi la case 7
CP (HL)
JR Z,nostats
;
; - La présence de SHIFT ou CTRL ou les 2 a été détectée -
;
LD HL,buf1+2 ;Reprendre la case 3eme ligne
PUSH AF
OR #A0 ;Or #A0 (10100000) A pour effet de mettre l'octet
LD (HL),A ;a &FF si la case contenait CTRL ou SHIFT seuls.
POP AF ;Dans le cas ou SHIFT - CTRL sont combines avec
; ;une autre touche sur la me^me ligne , le code de
AND #A0 ;celle ci-se trouve restaurée .
JR Z,shiftctrl
AND #20 ;Ensuite ces 3 comparaisons permettent de
JR NZ,ctrl ;déterminer SHIF & CTRL ou les 2
shift: LD A,#20
JR setstat
ctrl : LD A,#80
JR setstat
shiftctrl:
LD A,#A0
setstat:
LD (statkey),A
;
;- Traitement des touches sans CTRL ni SHIFT . 1 Chercher la ligne -
;
nostats:
LD HL,buf1 ;On balaie les 10 octets du buffer .
LD C,0 ;Tant que #FF , aucune touche sur cette ligne
LD B,10 ;et on ajoute 8 au compteur pour prendre en
findline: ;compte la ligne suivante .
LD A,(HL)
CP #FF
JR NZ,trouve
&nb sp; LD A,8
ADD A,C
LD C,A
INC HL
DJNZ findline
RET
;
;- 2 Chercher la touche -
;
trouve:
LD B,0 ;Or #20 pour passer #5F en #7F dans le cas ou
CP #5F ;dernière touche +CTRL + SHIFT mais tester
JR NZ,findkey ;avant car #DF OR #20 = #FF et dans ce
OR #20 ;cas on reste coince dans la boucle !
findkey:
;RRC A ;Rotation a droite
JR NC,keyfind ;Si bit a 0 : Touche trouvée
INC B
JR findkey
;
keyfind:
LD A,C ;Ajouter le numéro de ligne au numéro de colonne
ADD A,B
nokey: LD (numkey),A ;Et nous avons enfin notre numéro INKEY
RET
;
;- Les valeurs des 8 touches dans 1 ligne pour comparaison -
;
bitmap:
DB #FE,#FD,#FB,#F7,#EF,#DF,#BF,#7F
*LIST ON
numkey:
DB 0
statkey:
DB 0
;
;- Buffer de stockage des 10 lignes clavier -
;
buf1 : DB #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
;

NOTE

On peut remplacer la section de programme (tirée des ROMS) située à entre les 2 ligne d'astériques par :

LD BC,#F792 ;Initialiser directement le PPI en lecture
OUT (C),C ;clavier
LD B,#F6
LD C,#40
;
LD HL,buf1 ;Départ du buffer pour les 10 lignes
bcl : LD B,#F6 ;Envoyer l'ordre de lecture .
OUT (C),C
LD B,#F4 ;Lire le registre R14 sur le port A qui nous donne
IN A,(C) ;l'octet transmis par le clavier . (#FF si aucune
LD (HL),A ;touche enfoncée) .
INC HL ;Adresse stockage ligne suivante .
INC C ;Incrémenter pour lire la ligne clavier suivante .
LD A,C
AND #F ;Tester si on atteint la 10eme ligne
CP 10
JR NZ,bcl ;Sinon recommencer
;
POP AF ;Si cette routine est utilisée sous interruption
POP BC ;Placer un RET après EI et n'appeler la routine de
POP HL ;décodage que quand c'est nécéssaire .
EI


Dans ce cas , en sortie de routine , les ports E/S systéme se trouvent plutot perturbés . Ce n'est pas bien grave car tous les 1/50S. , AMSDOS effectue une lecture clavier et restaure l'ordre normal des choses . En employant cette seconde version (Ne figure pas en code binaire sur la disquette) :

10 CALL 40000:GOTO 10 .

Ceci plante complètement car le système n'a pas le temps de repasser par sa routine lire clavier .

10 CALL 40000:FOR tp=1 TO 20:NEXT:GOTO 10

Tout va bien car on laisse au cycle d'interruption le temps de se produire .

D'autres détails dans l'article : Buffer clavier AMSDOS .

★ ANNÉE: ???
★ AUTEUR: MICHEL MAIGROT

★ AMSTRAD CPC ★ DOWNLOAD ★

Other platform tool:
» SOS3KEYBOARDDATE: 2011-06-05
DL: 382
TYPE: ZIP
SiZE: 6Ko
NOTE: 40 Cyls
.HFE: Χ

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

Lien(s):
» Applications » Problèmes de compatibilité CPC/CPC Plus (Tom et Jerry/GPA)
» Coding Src's » Keyboard II (Schneider Magazin)
» Hardware » Depannage - CPC 664 Membrane Clavier
» Coding » Clefs1 15 Logiciel Interne Table Clavier
» Applications » Vocaclavier
» Applications » Turbo - Clavier (CPC Revue)
Je participe au site:
» Vous avez des infos personnel, des fichiers que nous ne possédons pas concernent ce programme ?
» 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 142 millisecondes et consultée 3620 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.