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=> | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Lignes | | | | | | | | | 0 | F.Hau | F.Dro | F.Bas | Pn. 9 | Pn. 6 | Pn. 3 | Pn.En | Pn. . | 1 | F.Gau | Copy | Pn. 7 | Pn. 8 | Pn. 5 | Pn. 1 | Pn. 2 | Pn. 0 | 2 | CLR | "[" | Enter | "]" | Pn. 4 | SHIFT | "ç" | 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" | 9 | J.hau | J.bas | J.gau | J.dro | J.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 = &5BOu 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 10Tout va bien car on laisse au cycle d'interruption le temps de se produire . D'autres détails dans l'article : Buffer clavier AMSDOS . ★ AMSTRAD CPC ★ DOWNLOAD ★ |
CPCrulez[Content Management System] v8.7-desktop/c Page créée en 142 millisecondes et consultée 3620 foisL'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. |
|
|
|