; SMILENGHEADER ; COMMENT This is the Smile NG file header, do not modify! ; VERSION 1.0 ; PROC CALM .PROC z80 .BASE 10'16 ;-------------------------------------------------------------------------------------------------------------------------------------------+ ; Programme qui permet d'utiliser le clavier avec interruption, en mode 0 (compatible i8080) | ; Version 1.0 | ; Gilbert Conus | ; IMPORTANT : DOIT FONCTIONNER À 5 MHZ !!! NE FONCTIONNE PAS À 2.5 MHZ !!! | ;-------------------------------------------------------------------------------------------------------------------------------------------+ ;-----------------------------------------------------------+ ; Adresses de périphériques | ;-----------------------------------------------------------+ ; Port mubus MUBUSL = 0 MUBUSH = 1 MUBUSRD = 10 ; Port écran LCD alphanumérique LCDWRI = 40 LCDWRD = 41 LCDRDI = 42 LCDRDD = 43 ; Port du clavier KBWR = 60 ; Pour écrire D7 = donnée D1 = Clock KBRD = 61 ; Pour lire D7 = donnée D1 = Clock KBLATCH = 62 ; Pour pour permettre (D0=0) ou interdire(D0=1) le rst 10h ; Port écran graphique SCRDAT = 0C0 SCRCMD = 0C1 ; Port parallèle PARADATA = 0E0 PARAFLAG = 0E1 PARAINIT = 0E2 ;-----------------------------------------------------------+ ; Fin des adresses de périphériques | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Adresses des variables en RAM | ;-----------------------------------------------------------+ ; Pour le test de RAM (elles ne doivent plus êtres utilisées après le test) UN = 4000 DI = 4001 CE = 4002 MI = 4003 DM = 4004 ; Adresses mémoire (variables en RAM) KB_GET_SC_RET = 4000 ; Pour consulter une éventuelle valeur de retour de _KB_GET_SC KB_FLAGS1 = 4001 ; FLAGS du drapeau (identique à celui du IBM PC-AT) KB_FLAGS2 = 4002 ; BIT Description ; 0 Touche maj droite enfoncée ; 1 Touche Maj Gauche enfoncée ; 2 Une des deux touches Ctrl enfoncée ; 3 Une des deux touches Alt enfoncée ; 4 Touche Scroll Lock active ; 5 Touche Num Lock active ; 6 Touche Caps Lock active ; 7 Touche Insert active ; 8 Touche Ctrl gauche enfoncée (inutlisé) ; 9 Touche Alt gauche enfoncée ; 10 Touche Ctrl droite enfoncée (inutilisé) ; 11 Touche Alt gr droite enfoncée ; 12 Touche Scroll Lock enfoncée (inutilisé) ; 13 Touche Num Lock enfoncée (inutilisé) ; 14 Touche Caps lock enfoncée (inutilisé) ; 15 Touche SysRq enfoncée KB_TYPEMATIC_RATE_DELAY = 4003 ; Taux de répétition et délai ; bits 0-4 = taux de répétition 0 = le plus rapide, 1f = le plus lent ; et bits 5-6 = délai en secondes (1 et 0.25s ; 2 = 0.5s ; 3 = 0.75s et 4 = 1s) KB_BUFFER_H = 4005 ; Pointeur sur la tête du buffer clavier (head) (position la plus basse actuelle) KB_BUFFER_T = 4007 ; Pointeur sur la queue du buffer clavier (tail) (limite à ne pas déborder) KB_BUFFER = 4009 ; Adresse normale de départ de la FIFO du clavier, longueur de 64 octets par défaut ; Cette valeur peut être modifiée, en changeant la valeur de KB_BUFFER_T SC2ASCII_START = 4050 ; Adresse de départ de la table de décodage des scan-codes stockée ici SC2ASCII_END = 4052 ; Adresse de fin de la table de décodage des scan-codes stockée ici ; Variables écran graphique pour le clavier TX_CURRENT_PAGE = 4054 ; Adresse de départ de la page texte courrante GR_CURRENT_PAGE = 4056 ; Adresse de départ de la page graphique courante TX_CURRENT_POS = 4058 ; Adresse actuelle du pointeur en mode texte GR_CURRENT_POS = 405A ; Adresse actuelle du pointeur en mode graphique CURSOR = 405C ; coordonnées du curseur sur 16 bits CURSOR_X = 405C ; abscisse du curseur (0;0 est en haut à gauche de l'écran) CURSOR_Y = 405D ; ordonnée du curseur PRINTER_CONNECTED = 405E ; bit 0 à 1 s'il y a une imprimante, sinon à 0 GLOBAL_TEMP = 4060 ; variable globale qui sert à tout le monde ;-----------------------------------------------------------+ ; Fin des adresses des variables en RAM | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Constantes | ;-----------------------------------------------------------+ .base 10'2 ; Pour le clavier ; Rappel : Pour la lecture : D7 = donnée, D1 = Clock ; Pour l'écriture : D7 = donnée, D1 = Clock, D2 = ENDATA (logique bas), D3 = ENCLK (logique bas) KB_MSK = 10000010 ; Masque clavier, ne garde que D7 et D1 KB_MSK_D = 10000000 ; Masque clavier, ne garde que le bit de donnée KB_MSK_C = 00000010 ; Masque clavier, ne garde que le bit de clock KB_ADD_B = 00000000 ; permet de valider la ligne de donnée ET la ligne de clock KB_ADD_D = 00001000 ; ne valide que la ligne de donnée KB_ADD_C = 00000100 ; Ne valide que la ligne de clock KB_ADD_N = 00001100 ; Interdit la ligne de donnée ET la ligne de clock ;-----------------------------------------------------------+ ; Pour l'écran LCD alphanumérique FINIT = 00110000 ; Valeur d'initialisation FSET = 00111000 ; Function SET (8 bits, char 5x8 px) DISP = 00001100 ; Display ON, Cusror OFF, Blink OFF ; Pour avoir le curseur : DISP+1 CLRDSP = 00000001 ; Efface l'écran, remet à la position initiale EMSET = 00000110 ; Entry Mode Set (fin de l'initialisation) PAHAUT = 10000000 ; Page/rangée supérieure de l'écran PABAS = 11000000 ; Page/rangée inférieure de l'écran BUSY = 10000000 ; Masque pour vérifier l'état du flag busy (qui est sur D7) ;-----------------------------------------------------------+ .base 10'16 ; Pour l'écran LCD graphique ; Ecran 240x128 pixels ; mode 8x8 (un caractère occupe 8x8 pixels) ; 30 colonnes x 16 lignes THA = 40 ; text home address set TA = 41 ; text area set GHA = 42 ; graphic home address set GA = 43 ; graphic area set CURSET = 21 ; set cursor pointer OFFSET = 22 ; offset register set ADPSET = 24 ; address pointer set AWRON = 0B0 ; Autowrite ON AWROFF = 0B2 ; Autowrite OFF ARDON = 0B1 ; Autoread ON ARDOFF = 0B2 ; Autoread OFF ;-----------------------------------------------------------+ ; Fin des constantes | ;-----------------------------------------------------------+ ; Start .loc 0 jump start .ascii "FS22-647" ; Interruption clavier (lorsqu'elle se lance, on dispose de 25 us pour agir, soit 125 cycles d'horloges à 5 MHz) ; En fait, au mieux, on a le droit à 250 cycles d'horloge si le clavier fonctionne à 10kHz, au pire 125, si le clavier fonctionne à 20 kHz) ; En arrivant ici, 11 cycles d'horloge (rst 10h) se sont passé au minimum et au maximum 34 (les opérations les plus longues avec IX et IY prennent 23 cycles), ; l'addition de 11+23 nous donne bien 34. Prenons toujours le pire cas. (voir le compte sour _KB_GET_SC) .loc 10 call _KB_GET_SC ; Acquiert le scan code (17 cycles) => 77 cycles pour entrer maximum. ion ; Interruptions à nouveau actives reti ; Fin de l'interruption ; Pour les autres vecteurs d'interruption .loc 18 ion ; Interruptions à nouveau actives reti ; Fin de l'interruption .loc 20 ion ; Interruptions à nouveau actives reti ; Fin de l'interruption .loc 28 ion ; Interruptions à nouveau actives reti ; Fin de l'interruption .loc 30 ion ; Interruptions à nouveau actives reti ; Fin de l'interruption .loc 38 ion ; Interruptions à nouveau actives reti ; Fin de l'interruption ; Petit message .loc 40 .ascii "2004-2007 www.Avenir-OpenWork.info" ; Et pour l'interruption non masquable .loc 66 retn ; Programme principal ici .loc 70 ; permet par la suite d'implémenter aussi une NMI start: move #0bfff,sp ; Initialise le stack pointer au sommet de la RAM call _WAIT100ms ; Laisse le temps à tous les périphériques d'atteindre les bons seuils de tension move #0,a move a,$MUBUSL move a,$MUBUSH ; éteind les leds mubus move #1,a move a,$KBLATCH ; le clavier ne peut pas encore faire des interruptions ;call _WAIT100ms ; Laisse le temps à tous les périphériques d'atteindre les bons seuils de tension call _LCDTX_INIT ; initialise le LCD texte call _LCDTX_CLS ; efface l'écran ; AJOUTER ICI VÉRIFICATION SI UNE IMPRIMANTE EST CONNECTÉE ; Exécution du boot, avec vérification de mémoire, à ce stade. Boot: ; Fixe les adresses de départ pour le texte et les graphiques ; Avec le texte en bas de la RAM vidéo. Chaque page écran texte prend 1E0 octets en mode 16x30. Il y a donc 15 pages de texte. ; Chaque page graphique prend F00 octets, il y a donc de 1c20 à 7fff 6 pages graphiques. move #0000,hl ; text home address = 0h move hl,TX_CURRENT_PAGE ; Sauve la page texte active actuelle call dt2 move #THA,a call _LCDGR_CMD move #1c20,hl ; graphic home address = 1c20 move hl,GR_CURRENT_PAGE ; Sauve la page graphique active actuelle call dt2 move #GHA,a call _LCDGR_CMD ; Défini la largeur d'écran move #001E,hl ; zone texte de 30 colonnes call dt2 move #TA,a call _LCDGR_CMD move #001E,hl ; zone graphique de 30 colonnes call dt2 move #GA,a call _LCDGR_CMD ; Défini le mode d'affichage move #80,a ; mode OR call _LCDGR_CMD ; Set OFFSET register move #000e,hl ; La CG-RAM commence en 7400h pour le caractère 80h. Elle finit en 77FF pour le dernier caractère. call dt2 move #OFFSET,a call _LCDGR_CMD ; Mode d'affichage (texte OFF, Graphics ON, Curseur OFF) move #98,a call _LCDGR_CMD move GR_CURRENT_PAGE,hl ; Pointeur au départ call dt2 move #ADPSET,a call _LCDGR_CMD ; move #AWRON,a ; call _LCDGR_CMD move #0f00,bc ; 30 colonnes x 128 pixels = 3840 = 0F00h move #pict1,de ; Adresse de base de l'image call _LCDGR_WRGRAPH ; On affiche le dessin call _WAIT1s call _WAIT1s ; 2 secondes de pause ; Mode d'affichage (texte ON, Graphics OFF, Curseur ON, Blink ON) move #97,a call _LCDGR_CMD call _LCDGR_TX_CLMEM ; on rempli la mémoire vidéo, dédidée au texte, d'espaces, pour que toutes les pages soient vides. ; On écrit les codes ASCII manquant move #CHAR_tra,de ; caractère ASCII AA : ¬ move #7450,hl ; pointeur sur le caractère 8A en GC-RAM soit AA en ASCII call _LCDGR_WRCG move #CHAR_telque,de ; caractère ASCII DD : | move #75e8,hl ; pointeur sur le caractère BD en GC-RAM soit DD en ASCII call _LCDGR_WRCG move #CHAR_parag,de ; caractère ASCII F5 : § move #76a8,hl ; pointeur sur le caractère D5 en GC-RAM soit F5 en ASCII call _LCDGR_WRCG move #CHAR_degre,de ; caractère ASCII F8 : ° move #76c0,hl ; pointeur sur le caractère D8 en GC-RAM soit F8 en ASCII call _LCDGR_WRCG move #CHAR_umlaut,de ; caractère ASCII F9 : " move #76c8,hl ; pointeur sur le caractère D9 en GC-RAM soit F9 en ASCII call _LCDGR_WRCG move #CHAR_aaigu,de ; caractère ASCII A0: à move #7400,hl ; pointeur sur le caractère 80 en GC-RAM soit A0 en ASCII call _LCDGR_WRCG move #CHAR_iaigu,de ; caractère ASCII A1: ì move #7408,hl ; pointeur sur le caractère 81 en GC-RAM soit A1 en ASCII call _LCDGR_WRCG move #CHAR_oaigu,de ; caractère ASCII A2: ò move #7410,hl ; pointeur sur le caractère 82 en GC-RAM soit A2 en ASCII call _LCDGR_WRCG move #CHAR_uaigu,de ; caractère ASCII A3: ù move #7418,hl ; pointeur sur le caractère 83 en GC-RAM soit A3 en ASCII call _LCDGR_WRCG move #CHAR_ntilde,de ; caractère ASCII A4: ñ move #7420,hl ; pointeur sur le caractère 84 en GC-RAM soit A4 en ASCII call _LCDGR_WRCG move #CHAR_atilde,de ; caractère ASCII C6: ã move #7530,hl ; pointeur sur le caractère A6 en GC-RAM soit C6 en ASCII call _LCDGR_WRCG move #CHAR_otilde,de ; caractère ASCII E4: õ move #7620,hl ; pointeur sur le caractère C4 en GC-RAM soit E4 en ASCII call _LCDGR_WRCG ; On écrit un petit texte quand même :) move #0022,hl ; Pointeur sur la 2è ligne 5è colonne move hl,TX_CURRENT_POS ; indique la nouvelle position mémoire call dt2 move #ADPSET,a call _LCDGR_CMD ; move #AWRON,a ; call _LCDGR_CMD ; Autowrite ON move #LONGG1,b ; nombre de caractères à écrire move #msgg1,de call _LCDGR_WRSTR ; écrit le message ; Même chose avec le deuxième message move #0060,hl ; Pointeur sur la 4è ligne 7è colonne call dt2 move #ADPSET,a call _LCDGR_CMD ; move #AWRON,a ; call _LCDGR_CMD ; Autowrite ON move #LONGG2,b ; 16 caractères move #msgg2,de call _LCDGR_WRSTR ; écrit le message call _WAIT100ms ; On laisse un petit temps ; Affiche sur la console le soft aussi call _LCDTX_CLS move #LONG5,b ; longueur du message move #msg5,hl call _LCDTX_WRSTR call _LCDTX_CR move #LONG6,b ; longueur du message move #msg6,hl call _LCDTX_WRSTR ; On affiche le "programme" :p move #009D,hl ; Pointeur sur la 6è ligne 9è colonne call dt2 move #ADPSET,a call _LCDGR_CMD ; move #AWRON,a ; call _LCDGR_CMD ; Autowrite ON move #LONGG3,b ; 16 caractères move #msgg3,de call _LCDGR_WRSTR ; écrit le message ; Compteur de RAM ici move #009B,hl ; Pointeur sur la 3è ligne 7è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move #30,a move a,DI move a,CE move a,MI move a,DM move #35,a ; 5 move a,UN move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 move #4005,ix ; initialisation d'IX, le pointeur tstram: move #55,a ; 01010101 valeur de test move a,{ix} ; On met la valeur de test où IX pointe move {ix},a ; Et on la récupère comp #55,a ; Est-ce la même? jump,ne fin ; si on n'a pu l'acquérir, alors on est au sommet de la RAM move UN,a comp #39,a jump,eq ajdi inc a move a,UN move #009B,hl ; Pointeur sur la 3è ligne 7è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move UN,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche l'unité inc ix jump tstram ajdi: move #30,a move a,UN ; Remise à 0 des unités move #009B,hl ; Pointeur sur la 3è ligne 7è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move UN,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche l'unité move DI,a comp #39,a jump,eq ajce inc a move a,DI move #009A,hl ; Pointeur sur la 3è ligne 6è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move DI,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche la dizaine inc ix jump tstram ajce: move #30,a move a,DI ; Remise à 0 des unités move #009A,hl ; Pointeur sur la 3è ligne 6è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move DI,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche la dizaine move CE,a comp #39,a jump,eq ajmi inc a move a,CE move #0099,hl ; Pointeur sur la 3è ligne 5è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move CE,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche la centaine inc ix jump tstram ajmi: move #30,a move a,CE ; Remise à 0 des unités move #0099,hl ; Pointeur sur la 3è ligne 5è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move CE,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche la centaine move MI,a comp #39,a jump,eq ajdm inc a move a,MI move #0098,hl ; Pointeur sur la 3è ligne 4è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move MI,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche le millier inc ix jump tstram ajdm: move #30,a move a,MI ; Remise à 0 des unités move #0098,hl ; Pointeur sur la 3è ligne 4è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move MI,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche le millier move DM,a comp #37,a jump,eq fin inc a move a,DM move #0097,hl ; Pointeur sur la 3è ligne 3è colonne call dt2 move #ADPSET,a call _LCDGR_CMD move DM,a move #0C4,b ; n'incrémente pas le pointeur call _LCDGR_WRCHR2 ; on affiche le di-millier inc ix jump tstram fin: move #00D2,hl ; Pointeur sur la 8è ligne 1ère colonne call dt2 move #ADPSET,a call _LCDGR_CMD ; move #AWRON,a ; call _LCDGR_CMD ; Autowrite ON move #LONGG4,b ; 16 caractères move #msgg4,de call _LCDGR_WRSTR ; écrit la chaine de caractères ; Le test mémoire est fini ici call _LCDTX_CLS ; efface le petit lcd alphanumérique call _PARA_PRINTINIT ; initialise l'imprimante im0 ; Prépare le mode d'interruptions masquées compatible i8080 ion ; Active les interruptions call _KB_INIT ; initialise le clavier call _WAIT1s ; attend 1 seconde pour lire move #010E,hl ; Pointeur sur la 10è ligne 1ère colonne move hl,TX_CURRENT_POS ; Sauve la position actuelle du pointeur call dt2 move #ADPSET,a call _LCDGR_CMD move #0000,hl move hl,TX_CURRENT_PAGE ; Rappel sur la position de page move #0A0,a call _LCDGR_CMD ; Cusreur 1 ligne move #0900,hl ; définit la position du curseur 10è ligne 1ère colonne move hl,CURSOR ; sauve les coordonnées call dt2 move #CURSET,a call _LCDGR_CMD ; place le curseur Boucle: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq Boucle ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq Boucle ; non, alors on attend le suivant comp #5e,a ; circonflexe? jump,eq wrcirc comp #0f9,a ; umlaut ? jump,eq wruml comp #60,a ; accent grave? jump,eq wrgrave comp #0ef,a ; accent aigu ? jump,eq wraigu comp #7e,a ; tilde? jump,eq wrtilde wrchr: move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; oui, alors on affiche le caractère call _LCDGR_INCCUR ; incrémente de curseur jump boucle ; Attend l'interruption wrcirc: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq wrcirc ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq wrcirc ; non, alors on attend le suivant comp #61,a ; a minuscule ? jump,eq wracirc comp #65,a ; e minuscule ? jump,eq wrecirc comp #69,a ; i minuscule ? jump,eq wricirc comp #6f,a ; o minuscule ? jump,eq wrocirc comp #75,a ; u minuscule ? jump,eq wrucirc move a,d ; sinon on sauve le caractère move #5e,a move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; alors on affiche le circonflexe call _LCDGR_INCCUR ; incrémente de curseur move d,a ; on récupère le caractère autre qu'une voyelle jump wrchr ; et on poursuit normalement wracirc: move #83,a ; a circonflexe jump wrchr ; on écrit le caractère wrecirc: move #88,a ; e circonflexe jump wrchr ; on écrit le caractère wricirc: move #8c,a ; i circonflexe jump wrchr ; on écrit le caractère wrocirc: move #93,a ; o circonflexe jump wrchr ; on écrit le caractère wrucirc: move #96,a ; u circonflexe jump wrchr ; on écrit le caractère wruml: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq wruml ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq wruml ; non, alors on attend le suivant comp #61,a ; a minuscule ? jump,eq wrauml comp #65,a ; e minuscule ? jump,eq wreuml comp #69,a ; i minuscule ? jump,eq wriuml comp #6f,a ; o minuscule ? jump,eq wrouml comp #75,a ; u minuscule ? jump,eq wruuml move a,d ; sinon on sauve le caractère move #0f9,a move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; alors on affiche le umlaut call _LCDGR_INCCUR ; incrémente de curseur move d,a ; on récupère le caractère autre qu'une voyelle jump wrchr ; et on poursuit normalement wrauml: move #84,a ; a umlaut jump wrchr ; on écrit le caractère wreuml: move #89,a ; e umlaut jump wrchr ; on écrit le caractère wriuml: move #8b,a ; i umlaut jump wrchr ; on écrit le caractère wrouml: move #94,a ; o umlaut jump wrchr ; on écrit le caractère wruuml: move #81,a ; u umlaut jump wrchr ; on écrit le caractère wrgrave: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq wrgrave ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq wrgrave ; non, alors on attend le suivant comp #61,a ; a minuscule ? jump,eq wragrave comp #65,a ; e minuscule ? jump,eq wregrave comp #69,a ; i minuscule ? jump,eq wrigrave comp #6f,a ; o minuscule ? jump,eq wrograve comp #75,a ; u minuscule ? jump,eq wrugrave move a,d ; sinon on sauve le caractère move #60,a move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; alors on affiche l'accent grave call _LCDGR_INCCUR ; incrémente de curseur move d,a ; on récupère le caractère autre qu'une voyelle jump wrchr ; et on poursuit normalement wragrave: move #85,a ; a grave jump wrchr ; on écrit le caractère wregrave: move #8a,a ; e grave jump wrchr ; on écrit le caractère wrigrave: move #8d,a ; i grave jump wrchr ; on écrit le caractère wrograve: move #95,a ; o grave jump wrchr ; on écrit le caractère wrugrave: move #97,a ; u grave jump wrchr ; on écrit le caractère wraigu: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq wraigu ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq wraigu ; non, alors on attend le suivant comp #61,a ; a minuscule ? jump,eq wraaigu comp #65,a ; e minuscule ? jump,eq wreaigu comp #69,a ; i minuscule ? jump,eq wriaigu comp #6f,a ; o minuscule ? jump,eq wroaigu comp #75,a ; u minuscule ? jump,eq wruaigu move a,d ; sinon on sauve le caractère move #0ef,a move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; alors on affiche l'accent grave call _LCDGR_INCCUR ; incrémente de curseur move d,a ; on récupère le caractère autre qu'une voyelle jump wrchr ; et on poursuit normalement wraaigu: move #0a0,a ; a aigu jump wrchr ; on écrit le caractère wreaigu: move #82,a ; e aigu jump wrchr ; on écrit le caractère wriaigu: move #0a1,a ; i aigu jump wrchr ; on écrit le caractère wroaigu: move #0a2,a ; o aigu jump wrchr ; on écrit le caractère wruaigu: move #0a3,a ; u aigu jump wrchr ; on écrit le caractère wrtilde: call _ReadKB ; lit le clavier comp #0,a ; caractère à afficher? jump,eq wrtilde ; non, alors on attend le suivant comp #1,a ; caractère à afficher? jump,eq wrtilde ; non, alors on attend le suivant comp #61,a ; a minuscule ? jump,eq wratilde comp #6f,a ; o minuscule ? jump,eq wretilde comp #6e,a ; n minuscule ? jump,eq writilde move a,d ; sinon on sauve le caractère move #0ef,a move #0C0,b ; incrémente le pointeur call _LCDGR_WRCHR ; alors on affiche l'accent grave call _LCDGR_INCCUR ; incrémente de curseur move d,a ; on récupère le caractère autre qu'une voyelle jump wrchr ; et on poursuit normalement wratilde: move #0c6,a ; a tilde jump wrchr ; on écrit le caractère wretilde: move #0e4,a ; o tilde jump wrchr ; on écrit le caractère writilde: move #0a4,a ; n tilde jump wrchr ; on écrit le caractère ;-----------------------------------------------------------+ ; Fonctions "haut-niveau" | ;-----------------------------------------------------------+ ; Fonction qui lit le buffer attend qu'une touche convertible en code ascii soit pressée ; tient compte des touches maj, ctrl, alt, num lock, etc. ; retourne 0 en A, et effectue les modification nécessaires s'il s'agit d'une touche "fonction" ; sinon retourne le code ASCII en A _ReadKB: push hl push de rk01$: call _KB_READ_BUFF ; on lit simplement le buffer, cette technique permet d'éviter des retards dûs à l'attente d'une pression ; d'une touche, alors qu'il y a déjà des données dans le buffer comp #86,a ; oui, alors on attend qu'une touche soit entrée jump,ne rk02$ ; non, alors on regarde s'il s'agit d'une touche de "fonction" call _KB_WAIT_SC ; attend une touche, le scan-code lu est en a rk02$: comp #0f0,a ; touche relâchée? jump,eq rkReleased ; oui alors on regarde quelle touche a été relâchée comp #0e0,a ; touche étendue? jump,eq rkExtended ; oui alors on regarde de quelle touche étendue il s'agit comp #0e1,a ; pause? jump,eq rkBreak ; oui alors on attend une nouvelle frappe de pause, le système ne fait rien pendant ce temps comp #66,a ; Backspace? jump,eq rkBackspace ; oui alors on efface le dernier caractère comp #0d,a ; TAB? jump,eq rkTab ; oui alors on s'occupe du TAB comp #58,a ; CAPS LOCK? jump,eq rkCapsLock ; oui alors on change l'état comp #5A,a ; retour chariot? jump,eq rkCr ; oui alors on valide la commande comp #12,a ; majuscule gauche? jump,eq rkShiftL ; oui alors on active le mode majuscule comp #59,a ; majuscule droite? jump,eq rkShiftR ; oui alors on active le mode majuscule comp #14,a ; Contrôle gauche? jump,eq rkControl ; oui alors on active le mode contrôle comp #11,a ; Alternatif gauche? jump,eq rkAlternate ; oui alors on active le mode alternatif comp #77,a ; NUM LOCK? jump,eq rkNumLock ; oui alors on change l'état comp #7e,a ; SCROLL LOCK? jump,eq rkScrollLock ; oui alors on change l'état comp #84,a ; System Require? jump,eq rkSytemRq ; oui alors on livre le système ; Si ce n'est pas une de ces fonctions, alors il s'agit peut-être d'une fonction du pavé numérique. si num lock est off move a,d ; sauve a move KB_FLAGS1,a ; acquiert les flags test a:#5 ; Num Lock on ? jump,zc rk03$ ; oui ? alors, on prépare une table de conversion move d,a ; non, récupère le scan-code et on teste si le code lu vient du pavé numérique comme fonction comp #6C,a ; HOME? jump,eq rkHome ; oui alors on repasse au début de la ligne comp #6B,a ; Flèche gauche? jump,eq rkArrowL ; oui alors on recule d'un caractère comp #69,a ; END? jump,eq rkEnd ; oui alors on passe à la fin de la ligne comp #75,a ; Flèche haut? jump,eq rkArrowT ; oui alors on monte d'une ligne comp #73,a ; 5 du pavé numérique? jump,eq rk09 ; oui alors on ignore la touche comp #72,a ; Flèche bas? jump,eq rkArrowB ; oui alors on descend d'une ligne comp #70,a ; Insert? jump,eq rkInsert ; oui alors on change l'état comp #7D,a ; Page Up? jump,eq rkPageUp ; oui alors on monte d'une page comp #74,a ; Flèche droite? jump,eq rkArrowR ; oui alors on avance d'un caractère comp #7A,a ; Page Down? jump,eq rkPageDown ; oui alors on change l'état comp #71,a ; Delete? jump,eq rkDelete ; oui alors on efface le caractère juste devant move a,d ; re-sauve le scan-code ; Préparation de la table de conversion rk03$: move KB_FLAGS1,a ; acquiert les flags test a:#2 ; Controle actif? jump,zs rkFShl ; non, alors test si majuscule gauche est actif ? test a:#3 ; oui, alors test si alternatif est actif ? jump,zs rkFShl ; non, alors test si majuscule gauche est actif ? move #_SC2ASCII_AGR,hl ; oui ctrl + alt, alors on est en mode alt gr move hl,SC2ASCII_START move #_SC2ASCII_AGR_END,hl move hl,SC2ASCII_END jump rk04 ; et on analyse rkFShl: test a:#0 ; test si majuscule gauche est actif ? jump,zc rkFCapsLM ; oui, alors test si caps lock est actif test a:#1 ; non, alors test si majuscule droite est actif jump,zc rkFCapsLM ; oui, alors test si caps lock est actif test a:#6 ; non, alors test caps lock, s'il est actif ? jump,zs rkminnl ; s'il est inactif, on est en mode minuscule, on teste le num lock jump rkMAJnl ; sinon on est en mode majuscule, on teste le num lock rkFCapsLM: test a:#6 ; caps lock actif ? jump,zs rkMAJnl ; s'il est inactif, on est en mode majuscule, on teste le num lock jump rkminnl ; sinon on est en mode minuscule, on teste le num lock rkMAJnl: test a:#5 ; test si num lock est actif en mode majuscule jump,zc rkMAJKP ; s'il est actif, on défini la table de conversion avec key paddle move #_SC2ASCII_M,hl ; sinon, on définit la table majuscule sans key paddle move hl,SC2ASCII_START move #_SC2ASCII_M_NO_KP_END,hl move hl,SC2ASCII_END jump rk04 ; et on analyse rkMAJKP: move #_SC2ASCII_M,hl ; on définit la table majuscule avec key paddle move hl,SC2ASCII_START move #_SC2ASCII_M_KP_END,hl move hl,SC2ASCII_END jump rk04 ; et on analyse rkminnl: test a:#5 ; test si num lock est actif en mode majuscule jump,zc rkminKP ; s'il est actif, on défini la table de conversion avec key paddle move #_SC2ASCII_N,hl ; sinon, on définit la table minuscule sans key paddle move hl,SC2ASCII_START move #_SC2ASCII_N_NO_KP_END,hl move hl,SC2ASCII_END jump rk04 ; et on analyse rkminKP: move #_SC2ASCII_N,hl ; table minuscule avec key paddle move hl,SC2ASCII_START move #_SC2ASCII_N_KP_END,hl move hl,SC2ASCII_END ; et on analyse en rk04 une fois définit ; On va, ici, parcourir les tables définies, pour trouver le caractère ascii que l'on va rendre rk04: move d,a ; récupère le scan-code move SC2ASCII_START,hl ; hl pointe sur le début de la table à parcourir move SC2ASCII_END,de ; et de sur la fin rk05$: comp {hl},a ; cherche le scan-code jump,eq rk06$ ; trouvé, alors on va afficher la lettre push hl ; sauve temporairement hl subc de,hl ; hl = de-hl == 0 ? jump,zs rk07$ ; oui, alors on a fait toute la table et on n'a rien trouvé, le caractère est à ignorer pop hl ; sinon, on récupère hl inc hl inc hl ; on double incrémente hl jump rk05$ ; et on boucle rk06$: inc hl ; on a trouvé le scan-code, on prend le ASCII move {hl},a ; on le place en a pop de pop hl ; on récupère les registres ret ; et on retourne rk07$: pop hl ; si on a rien trouvé, erreur (le clavier aurait envoyé une valeur impossible?) jump rkError ; Ici vient le traitement des touches "fonctions" ; Une touche a été relâchée rkReleased: call _KB_READ_BUFF ; même principe qu'en rk01$ comp #86,a ; pas encore de valeur ? jump,ne rk08$ ; non, alors on regarde s'il s'agit d'une touche de "fonction" call _KB_WAIT_SC ; oui, alors on attend que la seconde partie du scan-code soit envoyée rk08$: comp #12,a ; majuscule gauche? jump,eq rkRelShiftL ; oui, alors on désactive le mode majuscule comp #59,a ; majuscule droite? jump,eq rkRelShiftR ; oui, alors on désactive le mode majuscule comp #14,a ; Contrôle gauche? jump,eq rkRelCtrl ; oui, alors on désactive le mode contrôle comp #11,a ; Alternatif gauche? jump,eq rkRelAlt ; oui, alors on désactive le mode alternatif comp #58,a ; Caps Lock? jump,eq rkChangeLeds ; oui, alors on allume/éteind la led comp #77,a ; Num Lock? jump,eq rkChangeLeds ; oui, alors on allume/éteind la led comp #7e,a ; Scroll Lock? jump,eq rkChangeLeds ; oui, alors on allume/éteind la led rk09: move #0,a ; pour toute autre touche, on met 0 dans A, il n'y a rien à faire pop de pop hl ; on récupère les registres ret ; et on retourne ; Une touche étendue a été enfoncée rkExtended: call _KB_READ_BUFF ; même principe qu'en rk01$ comp #86,a ; pas encore de valeur ? jump,ne rk10$ ; non, alors on regarde de quelle "fonction" il s'agit call _KB_WAIT_SC ; oui, alors on attend que la seconde partie du scan-code soit envoyée rk10$: comp #0f0,a ; touche étendue relâchée? jump,eq rkRelExt ; oui, alors regarde quelle touche étendue a été relâchée comp #11,a ; Alternatif GR droite? jump,eq rkAltGr ; oui alors on active le mode alternatif GR ( = CTRL + ALT) comp #14,a ; Contrôle droite? jump,eq rkControl ; oui alors on active le mode contrôle comp #7C,a ; Print Screen? jump,eq rkPrintScr ; oui alors on active le mode contrôle comp #70,a ; Insert? jump,eq rkInsert ; oui alors on change l'état comp #71,a ; Delete? jump,eq rkDelete ; oui alors on efface le caractère juste devant comp #6C,a ; HOME? jump,eq rkHome ; oui alors on repasse au début de la ligne comp #69,a ; END? jump,eq rkEnd ; oui alors on passe à la fin de la ligne comp #7D,a ; Page Up? jump,eq rkPageUp ; oui alors on monte d'une page comp #7A,a ; Page Down? jump,eq rkPageDown ; oui alors on change l'état comp #6B,a ; Flèche gauche? jump,eq rkArrowL ; oui alors on recule d'un caractère comp #75,a ; Flèche haut? jump,eq rkArrowT ; oui alors on monte d'une ligne comp #72,a ; Flèche bas? jump,eq rkArrowB ; oui alors on descend d'une ligne comp #74,a ; Flèche droite? jump,eq rkArrowR ; oui alors on avance d'un caractère comp #4A,a ; Slash pavé numérique? jump,eq rkSlash ; oui alors on ajoute le slash comp #5A,a ; Enter pavé numérique? jump,eq rkCr ; oui alors on valide la commande comp #7e,a ; Pause si controle actif? jump,eq rkBreak2 ; oui alors on valide la commande jump rkError ; il n'existe pas d'autre touches étendues, si a est différent, alors erreur. ; La touche pause a été enfoncée ; Le système est en pause jusqu'à ce qu'à nouveau la touche pause aie été enfoncée ; Rappel: Pause n'a pas de break-code, et son make code est ; E1, 14, 77, E1, F0, 14, F0, 77 rkBreak: call _KB_READ_BUFF ; même principe qu'en rk01$ comp #86,a ; pas encore de valeur ? jump,ne rk11b$ ; non, alors on regarde si on a rappuyé sur pause rk11$: call _KB_WAIT_SC ; oui, lit l'octet suivant rk11b$: comp #0e1,a ; tant que la valeur est différente de E1h, on ne fait rien jump,ne rk11$ rk12$: call _KB_WAIT_SC ; lit l'octet suivant comp #14,a jump,ne rk12$ rk13$: call _KB_WAIT_SC ; lit l'octet suivant comp #77,a jump,ne rk13$ rk14$: call _KB_WAIT_SC ; lit l'octet suivant comp #0e1,a jump,ne rk14$ rk15$: call _KB_WAIT_SC ; lit l'octet suivant comp #0f0,a jump,ne rk15$ rk16$: call _KB_WAIT_SC ; lit l'octet suivant comp #14,a jump,ne rk16$ rk17$: call _KB_WAIT_SC ; lit l'octet suivant comp #0f0,a jump,ne rk17$ rk18$: call _KB_WAIT_SC ; lit l'octet suivant comp #77,a jump,ne rk18$ move #0,a pop de pop hl ; on récupère les registres ret ; on a fait notre pause ; Fait la même chose que Pause, mais avec un scan-code différent, n'a pas de brak-code non plus ; Cette pause ne pause que le temps que la touche est enfoncée. rkBreak2: call _KB_READ_BUFF ; même principe qu'en rk01$ comp #86,a ; pas encore de valeur ? jump,ne rk19b$ ; non, alors on regarde si on a rappuyé sur pause rk19$: call _KB_WAIT_SC ; lit l'octet suivant rk19b$: comp #0e0,a jump,ne rk19$ rk20$: call _KB_WAIT_SC ; lit l'octet suivant comp #0f0,a jump,ne rk20$ rk21$: call _KB_WAIT_SC ; lit l'octet suivant comp #7e,a jump,ne rk21$ move #0,a pop de pop hl ; on récupère les registres ret ; Efface le caractère et recule d'un caractère rkBackspace: move TX_CURRENT_POS,hl dec l ; recule d'un caractère move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD move #20,a move #0c4,b ; remplace le dernier caractère par un espace call _LCDGR_WRCHR call _LCDGR_DECCUR ; décrémente de curseur move #0,a pop de pop hl ; on récupère les registres ret ; Affiche 4 espace pour une tabulation rkTab: move #20,a ; espace move #0c0,b ; write and increment call _LCDGR_WRCHR call _LCDGR_WRCHR call _LCDGR_WRCHR call _LCDGR_WRCHR call _LCDGR_INCCUR ; incrémente de curseur call _LCDGR_INCCUR ; incrémente de curseur call _LCDGR_INCCUR ; incrémente de curseur call _LCDGR_INCCUR ; incrémente de curseur move #0,a pop de pop hl ; on récupère les registres ret ; CAPS LOCK : inverse l'état CAPS LOCK rkCapsLock: move KB_FLAGS1,a test a:#6 ; état du flag CAPS LOCK? jump,zs rk22$ ; inactif, alors on l'active clr a:#6 ; sinon, on le désactive le flag CAPS LOCK move a,KB_FLAGS1 jump rk23$ rk22$: set a:#6 ; active le flag CAPS LOCK move a,KB_FLAGS1 rk23$: move #0,a pop de pop hl ; on récupère les registres ret ; NUM LOCK : inverse l'état NUM LOCK rkNumLock: move KB_FLAGS1,a test a:#5 ; état du flag NUM LOCK ? jump,zs rk24$ ; inactif, alors on l'active clr a:#5 ; sinon, on le désactive le flag NUM LOCK move a,KB_FLAGS1 jump rk25$ rk24$: set a:#5 ; active le flag CAPS LOCK move a,KB_FLAGS1 rk25$: move #0,a pop de pop hl ; on récupère les registres ret ; SCROLL LOCK : inverse l'état SCROLL LOCK rkScrollLock: move KB_FLAGS1,a test a:#4 ; état du flag SCROLL LOCK ? jump,zs rk26$ ; inactif, alors on l'active clr a:#4 ; sinon, on le désactive le flag SCROLL LOCK move a,KB_FLAGS1 jump rk27$ rk26$: set a:#4 ; active le flag CAPS LOCK move a,KB_FLAGS1 rk27$: move #0,a pop de pop hl ; on récupère les registres ret ; valide la commande (pour l'interpréteur de commande) rkCr: ;Call _ReadCmd move #0,a pop de pop hl ; on récupère les registres ret ; Change le flag INSERT rkInsert: move KB_FLAGS1,a test a:#7 ; état du flag INSERT? jump,zs rk28$ ; inactif, alors on l'active clr a:#7 ; sinon, on le désactive le flag INSERT move a,KB_FLAGS1 call _LCDGR_CURSOR1L ; met un curseur fin en bas de ligne jump rk29$ rk28$: set a:#7 ; active le flag INSERT move a,KB_FLAGS1 call _LCDGR_CURSOR8L ; met un curseur actif sur toute la case de caractère rk29$: move #0,a pop de pop hl ; on récupère les registres ret ; Active le majuscule gauche rkShiftL: move KB_FLAGS1,a ; acquiert le flag set a:#1 ; active le flag MAJUSCULE GAUCHE move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Active le majuscule droite rkShiftR: move KB_FLAGS1,a ; acquiert le flag set a:#0 ; active le flag MAJUSCULE DROITE move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Active le flag contrôle rkControl: move KB_FLAGS1,a ; acquiert le flag set a:#2 ; active le flag CONTROL move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Active le flag alternatif rkAlternate: move KB_FLAGS1,a ; acquiert le flag set a:#3 ; active le flag ALTERNATIF move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Active les flags Control et Alternatif rkAltGr: move KB_FLAGS1,a ; acquiert le flag set a:#2 ; active le flag CONTROL set a:#3 ; active le flag ALTERNATIF move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Revient en début de page rkHome: ;call _LCDGR_GO_HOME move #0,a pop de pop hl ; on récupère les registres ret ; Va en fin de ligne rkEnd: ;call _LCDGR_GO_END move #0,a pop de pop hl ; on récupère les registres ret ; Remonte d'une page écran rkPageUp: call _LCDGR_PAGEUP move #0,a pop de pop hl ; on récupère les registres ret ; Descend d'une page écran rkPageDown: call _LCDGR_PAGEDOWN move #0,a pop de pop hl ; on récupère les registres ret ; Décale le pointeur RAM écran d'un caractère sur la gauche rkArrowL: call _LCDGR_GOLEFT move #0,a pop de pop hl ; on récupère les registres ret ; Décale le pointeur RAM écran d'un caractère sur le haut rkArrowT: call _LCDGR_GOTOP move #0,a pop de pop hl ; on récupère les registres ret ; Décale le pointeur RAM écran d'un caractère sur le bas rkArrowB: call _LCDGR_GOBOTTOM move #0,a pop de pop hl ; on récupère les registres ret ; Décale le pointeur RAM écran d'un caractère sur la droite rkArrowR: call _LCDGR_GORIGHT move #0,a pop de pop hl ; on récupère les registres ret ; Imprime la page écran en cours sur l'imprimante du port parallèle, si elle est connectée rkPrintScr: move PRINTER_CONNECTED,a comp #1,a ; imprimante connectée? jump,ne PrintScrAbort ; non alors on ne fait rien push bc ; sinon on sauve les registres, et on va imprimer l'écran move TX_CURRENT_POS,hl push hl ; sauve LCD_CURRENT_POS move #0000,hl move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD ; redéfinit le nouveau pointeur mémoire vidéo sur le début de l'écran move #GLOBAL_TEMP,hl ; on va copier l'écran dans la RAM à l'adresse GLOBAL_TEMP move #01e0,bc ; longueur d'un écran texte call _LCDGR_RDSTR2 ; on acquiert l'écran pop hl ; on récupère LCD_CURRENT_POS move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD ; redéfinit le pointeur mémoire vidéo sur sa position ; Ici on a une copie en ASCII de l'écran en GLOBAL_TEMP ; on va imprimer une ligne de 30 caractères puis écrire un passage à la ligne, et faire ceci 16 fois vu qu'on a 16 lignes move #10,d ; 16 lignes move #GLOBAL_TEMP,hl ; adresse de départ move #001e,bc ; 1 ligne de 30 caractères à imprimer prnscr: push de move #0a,a ; passage à la ligne call _PARA_PRINTCHR ; passe à la ligne call _PARA_PRINTSTR ; imprime la ligne add bc,hl ; hl va lire une ligne plus loin dans la mémoire pop de dec d jump,zc prnscr ; tant qu'on a pas fait toutes les lignes on continue pop bc move #0,a ; valeur de réussite pop de pop hl ; on récupère les registres ret PrintScrAbort: move #1,a pop de pop hl ; on récupère les registres ret ; Efface le caractère juste devant rkDelete: call _LCDGR_DEL move #0,a pop de pop hl ; on récupère les registres ret ; Place le code ASCII du 7 en A rkSlash: move #2f,a pop de pop hl ; on récupère les registres ret ; Vérifie quelle touche étendue a été relâchée rkRelExt: call _KB_READ_BUFF ; même principe qu'en rk01$ comp #86,a ; pas encore de valeur ? jump,ne rk30$ ; non, alors on regarde de quelle "fonction" il s'agit call _KB_WAIT_SC ; oui, alors on attend que la seconde partie du scan-code soit envoyée rk30$: comp #11,a ; ALT GR ? jump,eq rkRelAltGr comp #14,a ; Control droite? jump,eq rkRelCtrl move #0,a ; Toutes les autres touches étendues n'ont pas d'effet au relâchement pop de pop hl ; on récupère les registres ret ; Désactive le flag majuscule gauche rkRelShiftL: move KB_FLAGS1,a ; acquiert le flag clr a:#1 ; désactive le flag MAJUSCULE GAUCHE move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Désactive le flag majuscule droite rkRelShiftR: move KB_FLAGS1,a ; acquiert le flag clr a:#0 ; désactive le flag MAJUSCULE GAUCHE move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK pop de pop hl ; on récupère les registres ret ; Désactive le flag control rkRelCtrl: move KB_FLAGS1,a ; acquiert le flag clr a:#2 ; désactive le flag CONTROL move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK move #0,a pop de pop hl ; on récupère les registres ret ; Désactive le flag alternatif rkRelAlt: move KB_FLAGS1,a ; acquiert le flag clr a:#3 ; désactive le flag ALTERNATIF move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK move #0,a pop de pop hl ; on récupère les registres ret ; Désactive les flags control et alternatif rkRelAltGr: move KB_FLAGS1,a ; acquiert le flag clr a:#2 ; désactive le flag CONTROL clr a:#3 ; désactive le flag ALTERNATIF move a,KB_FLAGS1 ; modifie le flag move #0,a ; tout est OK move #0,a pop de pop hl ; on récupère les registres ret ; Pour l'instant ne fait rien encore rkSytemRq: move #0,a pop de pop hl ; on récupère les registres ret ; Touche Caps Lock relâchée, on change la LED rkChangeLeds: move KB_FLAGS1,a rr a rr a rr a rr a ; place les bits de LEDS en place 0 à 2 and #7,a ; met tous les autres à 0 move a,d ; sauve la commande rk31$: move #0ed,b ; Set/reset status indicator call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq rk31$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne rkError ; non, alors traitement d'erreur général rk32$: move d,b ; met les valeurs de leds à allumer/éteindre call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq rk32$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne rkError ; non, alors erreur move #0,a pop de pop hl ; on récupère les registres ret rkError: move #1,a ; en cas d'erreur dans un traitement, on renvoie 1 en a et on quitte pop de pop hl ; on récupère les registres ret ;-----------------------------------------------------------+ ; Fin des fonctions "haut-niveau" | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routines pour piloter le clavier | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routine qui "initialise" le clavier | ; | ; Entrée : rien | ; Sortie : rempli le buffer de 0 | ; Modifie : rien | ;-----------------------------------------------------------+ _KB_INIT: move #KB_BUFFER+40,hl move hl,KB_BUFFER_T ; Limite pour stocker les scan-codes définie à un buffer de 64 octets move #KB_BUFFER,hl move hl,KB_BUFFER_H ; Pointeur scan-code initialisé tout en bas du buffer organisé en FIFO move #KB_ADD_N,a move a,$KBWR ; désactive l'écriture du clock et de la ligne de donnée move #41,b move #0,a fill0$: move a,{hl} inc hl dj,ne b,fill0$ ; Rempli le buffer de 0 move a,KB_FLAGS1 move a,KB_FLAGS2 ; initialise les flags clavier à 0 move #_SC2ASCII_N,hl ; défini les variables de table de conversion par défaut move hl,SC2ASCII_START move #_SC2ASCII_N_KP_END,hl move hl,SC2ASCII_END ; Début de l'initialisation des commandes ici (num lock doit être actif par défaut) w00$: move #0ff,b ; reset (sert pour le cold reset) move #1,c ; étape 1 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande w000$: call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w00$ ; oui, alors renvoie la commande comp #0aa,a ; certains claviers n'ack pas la commande et l'exécutent directement. jump,eq w01$ comp #0fa,a ; acknowledge ? jump,eq w001$ comp #86,a ; en dernier cas, le buffer serait-il vide? jump,eq w000$ ; si c'était le cas, on attendrai encore la valeur de retour du clavier jump _KB_INIT_ERR ; sinon, alors dans tous les autres cas : erreur d'initialisation w001$: call _KB_WAIT_SC ; oui, on attend maintenant le BAT comp #0aa,a ; BAT Complete ? jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation w01$: move #0ed,b ; Set/reset status indicator move #2,c ; étape 2 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande w002$: call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w01$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,eq w02$ comp #86,a ; en dernier cas, le buffer serait-il vide? jump,eq w002$ ; si c'était le cas, on attendrai encore la valeur de retour du clavier jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation w02$: move #2,b ; oui alors on allume la led du num lock move #3,c ; étape 3 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w02$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation move KB_FLAGS1,a ; oui alors s'occupe du flag set a:#5 ; ajoute le num lock actif move a,KB_FLAGS1 ; et on modifie le flag w03$: move #0f3,b ; set typematic rate/delay move #4,c ; étape 4 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w03$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation w04$: move #2c,b ; délai = 0.5 sec ; répét rate = 10 cp/s move #5,c ; étape 5 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w04$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation move #2c,a ; place la valeur actuelle dans la variable move a,KB_TYPEMATIC_RATE_DELAY w05$: move #0f4,b ; enable move #6,c ; étape 6 (pour le traitement d'erreur) call _KB_SEND_CMD ; on envoi la commande call _KB_WAIT_SC ; et on attend une réponse du clavier comp #0fe,a ; resend ? jump,eq w05$ ; oui, alors renvoie la commande comp #0fa,a ; acknowledge ? jump,ne _KB_INIT_ERR ; non, alors erreur d'initialisation move #0db,a move a,$MUBUSH move a,$MUBUSL ; code de fin d'initialisation move #0,a move a,$KBLATCH ; le clavier est initialisé et libre ; Affichage du message sur l'écran que le clavier est initialisé move #LONG3,b ; longueur du message move #msg3,hl call _LCDTX_WRSTR call _LCDTX_CR ; on passe à la ligne move #LONG2,b ; longueur du message move #msg2,hl call _LCDTX_WRSTR ret ; et on retourne _KB_INIT_ERR: ; placer un éventuel message d'erreur ici move #0e7,a move a,$MUBUSH move c,a move a,$MUBUSL ; permet de montrer à quelle étape l'initialisation a raté. ; Affichage du message sur l'écran que l'initialisation du clavier a raté move #LONG3,b ; longueur du message move #msg3,hl call _LCDTX_WRSTR call _LCDTX_CR ; on passe à la ligne move #LONG4,b ; longueur du message move #msg4,hl call _LCDTX_WRSTR move #0,a move a,$KBLATCH ; le clavier est non-initialisé et libre ret ;-----------------------------------------------------------+ ; Fin de routine | ;-----------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Routine qui acquiert le scancode | ; | ; Entrée : rien | ; Sortie : place le scan-code en queue de FIFO | ; Modifie : rien | ;-------------------------------------------------------------------------------+ _KB_GET_SC: ex af ; Sauve l'accumulateur et les flags (4 cycles) ex bl ; Sauve les registres (4 cycles) move $KBRD,a ; Normalement en plein dans le bit de start (11 cycles) ; Il nous a donc fallu and #KB_MSK,a jump,zc _KB_GET_SC_ERR1 ; Si différent de 0, alors erreur move #0,b ; initialise b à 0, il contiendra le scan code move #8,c ; nombre de bits à acquérir d00$: move $KBRD,a ; sinon acquiert le premier bit de donnée, attend que le clock passe à 1 and #KB_MSK,a test a:#1 ; Clock à 1? jump,zs d00$ ; non alors on attend qu'il passe à 1 rr b ; décale pour le prochain bit d01$: move $KBRD,a ; lit le clavier and #KB_MSK,a test a:#1 ; Clock à 0? jump,zc d01$ ; non, alors on attend qu'il passe à 0 or b,a ; Ajoute le bit (Il n'y a pas besoin de masquer le bit de clock, puisqu'il est à 0) move a,b ; et le sauve dec c ; 1 bit de moins à acquérir jump,zc d00$ ; si c != 0, alors on continue d02$: move $KBRD,a ; sinon on s'occupe du bit de parité test a:#1 ; Clock à 1? jump,zs d02$ ; non alors on attend qu'il passe à 1 d03$: move $KBRD,a ; lit le clavier and #KB_MSK,a test a:#1 ; Clock à 0? jump,zc d03$ ; non alors on attend qu'il passe à 0 move a,c ; oui alors on sauve le bit de parité d04$: move $KBRD,a ; lit le clavier test a:#1 ; Clock à 1? jump,zs d04$ ; non alors on attend qu'il passe à 1 d05$: move $KBRD,a ; lit le clavier and #KB_MSK,a test a:#1 ; Clock à 0? jump,zc d05$ ; non alors on attend qu'il passe à 0 test a:#7 ; bit de stop à 1 ? jump,zs _KB_GET_SC_ERR2 ; si le bit de stop n'est pas à 1, alors il faut demander le renvoi d06$: move $KBRD,a ; lit le clavier test a:#1 ; Clock à 1? jump,zs d06$ ; non alors on attend qu'il passe à 1 ; À ce stade, la lecture du scan code est terminée. Il se trouve en b. On vérifie que le bit de parité est correct sinon aussi on redemande le renvoi, ; si tout est correct, on place le scancode à la fin de la FIFO et on termine l'interruption move #0ff,a and b,a ; le résultat de cette opération est le suivant : ; le flag P/V est à considérer comme parité, il est à 1, si le nombre de 1 est pair, et à 0 si le nombre de 1 est impair ; dans le résultat, mais comme FF contient un nombre pair de 1, on peut se baser sur b uniquement!! jump,pe d07$ ; on part contrôler si D7 de c est bien à 1 si le nombre de 1 est pair test c:#7 ; sinon on test qu'il soit à 0 car le nombre de bit est impair jump,zc _KB_GET_SC_ERR2 ; s'il ne l'est pas, erreur de transmission, on redemande l'envoi jump d08$ ; sinon tout est ok d07$: test c:#7 ; on test qu'il soit à 1 car le nombre de bit est pair jump,zs _KB_GET_SC_ERR2 ; s'il ne l'est pas, erreur de transmission, on redemande l'envoi ; Vérifie que le buffer peut encore accepter des scan-codes d08$: move KB_BUFFER_H,a move a,d ; Adresse relative (en effet les deux octets de poids fort valent 40) move KB_BUFFER_T,a comp d,a ; teste si la limite est atteinte jump,zs _KB_GET_SC_ERR3 ; si c'est le cas, le scan-code est ignoré move KB_BUFFER_H,hl ; sinon on fait pointer hl sur la tête du buffer move b,{hl} ; et on place le scan-code dans le buffer inc hl ; on incrémente hl move hl,KB_BUFFER_H ; et donc le pointeur de tête du buffer ; Ajout de la valeur lue sur le port mubus (écran de gauche) move b,a move a,$MUBUSL ; Fin de l'ajout move #0,a move a,KB_GET_SC_RET ; on retourne 0, comme quoi tout est ok move a,$KBLATCH ; Permet une nouvelle interruption clavier ex bl ; Récupère les registres en cours ex af ; Récupère l'accumulateur et le flag en cours ret ; et on a fini ; Erreur de type fatal, la lecture n'a pu se faire, alors il ertourne la valeur 1, et tout est abandonné _KB_GET_SC_ERR1: move #1,a move a,KB_GET_SC_RET move #0,a move a,$KBLATCH ; Permet une nouvelle interruption clavier ex bl ; Récupère les registres en cours ex af ; Récupère l'accumulateur et le flag en cours ret ; Erreur de transmission, le renvoi de l'octet est demandé. _KB_GET_SC_ERR2: move #0fe,b ; commande resend call _KB_SEND_CMD move #2,a move a,KB_GET_SC_RET move #0,a move a,$KBLATCH ; Permet une nouvelle interruption clavier ex bl ; Récupère les registres en cours ex af ; Récupère l'accumulateur et le flag en cours ret ; Erreur buffer plein, le scan-code est ignoré _KB_GET_SC_ERR3: move #3,a move a,KB_GET_SC_RET move #0,a move a,$KBLATCH ; Permet une nouvelle interruption clavier ex bl ; Récupère les registres en cours ex af ; Récupère l'accumulateur et le flag en cours ret ;-----------------------------------------------------------+ ; Fin de routine | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routine qui envoi un octet au clavier | ; | ; Entrée : la commande en b | ; Sortie : rien | ; Modifie : a | ;-----------------------------------------------------------+ _KB_SEND_CMD: ioff ; la première chose à faire et de couper les interruptions pendant que l'on écrit au clavier (pensez au SI/O2) push bc push de ; on sauve les registres move #1,a move a,$KBLATCH ; et d'interdir le déclanchement d'interrucption (qui serait faux, puisque l'on envoi des données) move #0ff,a and b,a ; Ensuite il faut définir le bit de parité jump,pe i00$ ; si il est pair, on met le bit de parité à 1 en D7 dans C move #8,c ; sinon on le place à 0, le nombre de bit étant déjà impair jump i01$ i00$: move #88,c ; note : dans les 2 cas, le 8 de poids faible sert à valider la donnée sur la sortie ; on retourne le nombre (d7 <-> d0 ; d6 <-> d1 ; d5 <-> d2 ; d4 <-> d3) i01$: move #0,a ; initialise le registre "retourné" à 0 test b:#7 ; d7 ?= 1 jump,zs i02$ ; non alors on passe à d6 set a:#0 ; oui alors on passe d0 à 1 i02$: test b:#6 ; d6 ?= 1 jump,zs i03$ ; non alors on passe à d5 set a:#1 ; oui alors on passe d1 à 1 i03$: test b:#5 ; d5 ?= 1 jump,zs i04$ ; non alors on passe à d5 set a:#2 ; oui alors on passe d2 à 1 i04$: test b:#4 ; d4 ?= 1 jump,zs i05$ ; non alors on passe à d5 set a:#3 ; oui alors on passe d3 à 1 i05$: test b:#3 ; d3 ?= 1 jump,zs i06$ ; non alors on passe à d5 set a:#4 ; oui alors on passe d4 à 1 i06$: test b:#2 ; d2 ?= 1 jump,zs i07$ ; non alors on passe à d5 set a:#5 ; oui alors on passe d5 à 1 i07$: test b:#1 ; d1 ?= 1 jump,zs i08$ ; non alors on passe à d5 set a:#6 ; oui alors on passe d6 à 1 i08$: test b:#0 ; d0 ?= 1 jump,zs i09$ ; non alors on passe à d5 set a:#7 ; oui alors on passe d7 à 1 ; ici a contient la valeur retuornée, ce qui est parfait, puisque l'on doit envoyer d0 en premier et d7 en dernier sur d7 ! i09$: move a,e ; sauve temporairement la commande move #8,d ; compteur du nombre de bits move #KB_ADD_C,a ; clock à 0 : phase d'inhibition move a,$KBWR ; on inhibe toute communication call _WAIT100us ; on attend 100us move #KB_ADD_B,a ; clock toujours à 0, descente du data move a,$KBWR ; on descend le data à 0 nop nop nop nop nop ; 4 us d'attente move #KB_ADD_D,a ; et on relâche le clock tout en maintenant le data à 0 move a,$KBWR ; c'est le "request-to-send" i10$: move $KBRD,a ; lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#1 ; clock à 0? jump,zc i10$ ; non, alors on attend qu'il passe à 0 move e,a ; oui alors on récupère la commande and #KB_MSK_D,a ; ne garde que la donnée or #KB_ADD_D,a ; et permet de la valider move a,$KBWR ; écrit le bit rl e ; décale la commande i11$: move $KBRD,a ; lit le clavier test a:#1 ; clock à 1? jump,zs i11$ ; non, alors on attend qu'il passe à 1 dec d ; 1 bit de moins à transmettre jump,zc i10$ ; tant que d != 0, il reste des bits à envoyer ; Ici les données sont envoyées, il reste le bit de parité sur D7 dans C et le bit de stop toujours à 1 i12$: move $KBRD,a ; lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#1 ; clock à 0? jump,zc i12$ ; non, alors on attend qu'il passe à 0 move c,a ; oui alors on prend le bit de parité move a,$KBWR ; on envoie le bit de parité i13$: move $KBRD,a ; lit le clavier test a:#1 ; clock à 1? jump,zs i13$ ; non, alors on attend qu'il passe à 1 i14$: move $KBRD,a ; lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#1 ; clock à 0? jump,zc i14$ ; non, alors on attend qu'il passe à 0 move #KB_ADD_N,a ; oui alors on relâche la ligne de donnée (et le clock) move a,$KBWR ; c'est le bit de stop nop ; temps pour laisser changer l'état i15$: move $KBRD,a ; lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#7 ; data à 0? jump,zc i15$ ; non, alors on attend qu'il passe à 0 i16$: move $KBRD,a ; oui, c'est l'ack du clavier, on vérifie que ce soit pareil pour le clock. Lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#1 ; clock à 0? jump,zc i16$ ; non, alors on attend qu'il passe à 0 i17$: move $KBRD,a ; Lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#7 ; data à 1? jump,zs i17$ ; non, alors on attend qu'il passe à 1 i18$: move $KBRD,a ; oui, alors pareil mais pour le clock. Lit le clavier and #KB_MSK,a ; ne garde que le clock et le data test a:#1 ; clock à 1? jump,zs i18$ ; non, alors on attend qu'il passe à 1 move #0,a move a,$KBLATCH ; Permet une nouvelle interruption clavier pop de pop bc ; récupère les registres ion ; et on réactive bien entendu aussi les interruptions ret ; alors le transfert est terminé ;-----------------------------------------------------------+ ; Fin de routine | ;-----------------------------------------------------------+ ;----------------------------------------------------------------------------------------------------------------------+ ; Routine qui lit le buffer clavier | ; | ; Entrée : rien | ; Sortie : le scancode en a (86h = aucun) | ; Pourquoi 86? car c'est une valeur quelconque qui n''est pas un scan-code | ; Modifie : a et radapte les pointeurs (décale) | ;-----------------------------------------------------------------------------------------------------------------------+ _KB_READ_BUFF: ioff ; interruptions inactives pendant la lecture du buffer push bc ; sauve les registres push de push hl move KB_BUFFER_H,a move a,d move #9,a comp d,a jump,zs _KB_READ_NO_SC ; si la différence fait 0, alors il n'y a pas de scan-codes move KB_BUFFER_H,hl ; sinon on acuiert le scan-code move #KB_BUFFER,bc notc ; par précaution, le carryflag = 0 subc bc,hl ; on soustrait KB_BUFFER à KB_BUFFER_H move h,b ; sinon on place la différence dans BC, move l,c ; cette paire de registre forme maintenant un compteur pour LDIR move KB_BUFFER,a ; place le scan code en a move #KB_BUFFER,de ; de est le pointeur de destination move #KB_BUFFER+1,hl ; hl est le pointeur de départ ldir ; décale toute la fifo move KB_BUFFER_H,hl dec hl move hl,KB_BUFFER_H ; définit le nouveau pointeur de tête (recule d'un octet dans la FIFO) pop hl pop de pop bc ; récupère les registres ion ; ré-actives les interruptions ret ; et retourne ; S'il n'y a pas de scan-codes, alors a = 86h et on retourne _KB_READ_NO_SC: move #86,a pop hl pop de pop bc ; récupère les registres ion ; ré-actives les interruptions ret ;-----------------------------------------------------------+ ; Fin de routine | ;-----------------------------------------------------------+ ;----------------------------------------------------------------------------------------------------------------------+ ; Routine qui lit le buffer clavier jusqu'à ce qu'un scan-code y soit inscrit | ; | ; Entrée : rien | ; Sortie : le scancode en a | ; Modifie : a | ;-----------------------------------------------------------------------------------------------------------------------+ _KB_WAIT_SC: wait ; on attend que la valeur soit écrite dans le buffer call _KB_READ_BUFF ; lit le buffer ret ; sinon elle est renvoyée en a ;-----------------------------------------------------------+ ; Fin de routine | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Fin des routines clavier AT | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routines de l'écran LCD alphanumérique | ;-----------------------------------------------------------+ ;Initialisation de l'écran LCD _LCDTX_INIT: move #0,a move a,$LCDWRI move #FSET,a move a,$LCDWRI call _WAIT10ms ; Il faut attendre plus de 4.1 ms move #FSET,a move a,$LCDWRI call _WAIT100us call _WAIT100us ; Il faut attendre plus de 100 us ;---------------------------------------------- move #FSET,a move a,$LCDWRI call _WAIT100us call _WAIT100us ; Il faut attendre plus de 100 us ;---------------------------------------------- move #FSET,a move a,$LCDWRI call _WAIT100us ; Il faut attendre plus de 40 us ;---------------------------------------------- move #DISP,a move a,$LCDWRI call _WAIT100us ; Il faut attendre plus de 40 us ;---------------------------------------------- move #CLRDSP,a move a,$LCDWRI call _WAIT1ms call _WAIT1ms ; Il faut attendre plus de 1.64 ms ;---------------------------------------------- move #EMSET,a move a,$LCDWRI call _WAIT100us ; Il faut attendre plus de 40 us ;---------------------------------------------- move #PAHAUT,a move a,$LCDWRI call _WAIT100us ; Il faut attendre plus de 40 us ;---------------------------------------------- ; message de fin, le périphérique est correctement initialisé move #LONG1,b ; longueur du message move #msg1,hl call _LCDTX_WRSTR ; on passe à la ligne call _LCDTX_CR ; on écrit la 2è ligne du message d'accueil move #LONG2,b ; longueur du message move #msg2,hl call _LCDTX_WRSTR ; tempo pour lire le message call _WAIT1s call _LCDTX_CLS ret ;========================================= ;========================================= ; Lecture du bit busy ; ATTENTION ROUTINE BUGUEE !!!! ; Tant qu'il est à 1, le LCD n'est pas prêt, dès qu'il passe à 0, on peut continuer ; méthode la plus rapide pour perdre le moins de temps possible lors d'écriture _LCDTX_WAIT: push af wlcd$: move $LCDRDI,a and #BUSY,a ; si le BF est à 0, on peut écrire sinon on ne peut pas. jump,zc wlcd$ ; jump Zero Clear / si c'est à 0 c'est fini sinon on boucle pop af ret ;========================================= ;========================================= ; écriture d'une chaîne de caractère sur le LCD ; entrée ; - Longueur de la chaine de caractères en B ; - Adresse du début de la chaine en HL ; sortie : - rien ; modifie: - A, B, HL _LCDTX_WRSTR: call _WAIT100us ; attendre plus de 40 us lcdw0$: move {HL},a ; acquérir le byte move a,$LCDWRD ; sortie du caractère sur l'écran call _WAIT100us ; Il faut attendre plus de 40 us inc hl ; pointage sur le caractère suivant dec b jump,ne lcdw0$ ; boucle jusqu'à ce que tous les caractères soient affichés ret ;========================================= ;========================================= ; écriture d'un caractère sur le LCD ; entrée ; - le caractère en A ; sortie : - rien ; modifie: - rien _LCDTX_WRCHR: call _WAIT100us ; Il faut attendre plus de 40 us move a,$LCDWRD ; affiche le caractère ret ;========================================= ;========================================= ; lecture d'un caractère sur le LCD ; entrée ; - adresse où sera copié le caractère en HL ; - adresse écran où se trouve le chr dans B ; sortie : - le caractère est copié où pointe HL ; modifie: - {HL} _LCDTX_RDCHR: call _WAIT100us ; Il faut attendre plusde 40 us ; on pointe où on va lire sur l'écran push af move b,a .base 10'2 or #10000000,a ; affecte D7 à 1 .base 10'16 move a,$LCDWRI pop af call _WAIT100us ; Il faut attendre plusde 40 us ; on lit et on copie move $LCDRDD,a move a,{HL} ret ;========================================= ;========================================= ; lecture d'une chaîne de caractères sur le LCD ; entrée ; - adresse où sera copié le caractère en HL ; - adresse écran où se trouve le début de la chaîne dans B ; - longueur de la chaîne de caractères dans C ; sortie : - la chaine est copiée à partir d'où pointe HL ; modifie: - A, C, HL _LCDTX_RDSTR: call _WAIT100us ; Il faut attendre plusde 40 us ; on pointe où on va lire sur l'écran push af move b,a .base 10'2 or #10000000,a ; affecte D7 à 1 .base 10'16 move a,$LCDWRI pop af rdstr1$: call _WAIT100us ; Il faut attendre plusde 40 us ; on lit et on copie move $LCDRDD,a move a,{hl} inc hl dec c move c,a comp #1,a jump,ne rdstr1$ ret ;========================================= ;========================================= ;carriage return ; entrée ; - rien ; sortie : - rien ; modifie - rien _LCDTX_CR: push af move #PABAS,a move a,$LCDWRI pop af call _WAIT100us ; attendre plus de 40 us ret ;========================================= ;========================================= ;Clrear Screen : efface l'écran et repositionne au départ ; entrée : - rien ; sortie : - rien ; modifie : - rien _LCDTX_CLS: push af move #CLRDSP,a move a,$LCDWRI pop af call _WAIT1ms call _WAIT1ms ; attendre plus de 1.64ms ret ;========================================= ;========================================= ; GO TO : déplace le curseur à l'adresse souhaitée sur l'écran ; entrée : - Adresse écran où se déplacer en A ; sortie : - rien ; modifie : - A _LCDTX_GOTO: .base 10'2 or #10000000,a ; affecte D7 à 1 .base 10'16 move a,$LCDWRI ret ;========================================= ;-----------------------------------------------------------+ ; Fin des routines LCD alphanumérique | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routines du LCD graphique | ;-----------------------------------------------------------+ ; Routine d'écriture de commande ; Entrée : commande en A ; Sortie : rien ; Modifie : rien _LCDGR_CMD: push af cmd1: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne cmd1 pop af move a,$SCRCMD ; écrit la commande ret ; Routine d'écriture avec un octet de donnée ; Entrée : data en A ; Sortie : rien ; Modifie : rien dt1: push af dt11: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne dt11 pop af move a,$SCRDAT ; écrit la donnée ret ; Routine d'écriture avec deux octets de donnée ; Entrée : data en HL ; Sortie : rien ; Modifie : A dt2: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne dt2 move l,a move a,$SCRDAT ; écrit la donnée de poids faible dt21: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne dt21 move h,a move a,$SCRDAT ; écrit la donnée de poids fort ret ; Routine du mode écriture automatique ; Entrée : data en A ; Sortie : rien ; Modifie : rien adt: push af adt1: move $SCRCMD,a and #8,a comp #8,a ; vérifie les bits de status jump,ne adt1 pop af move a,$SCRDAT ; écrit la donnée ret ; Routine du mode lecture automatique ; Entrée : rien ; Sortie : data en A ; Modifie : A adtr: move $SCRCMD,a and #4,a comp #4,a ; vérifie les bits de status jump,ne adtr move $SCRDAT,a ; lit la donnée ret ; Routine qui efface l'écran en mode texte ; Entrée : rien ; Sortie : rien ; Modifie :A _LCDGR_TX_CLS: ; On rempli l'écran de texte blanc (autrement dit, on l''efface!) push hl push bc move TX_CURRENT_PAGE,hl ; Pointeur au départ call dt2 move #THA,a call _LCDGR_CMD call dt2 move #ADPSET,a call _LCDGR_CMD move #AWRON,a call _LCDGR_CMD move #01e0,bc ; 30 colonnes x 16 lignes = 480 = 1E0h txcr: move #0,a call adt dec bc move b,a comp #0,a jump,ne txcr move c,a comp #0,a jump,ne txcr move #AWROFF,a ; fin de l'autowrite call _LCDGR_CMD pop bc pop hl ret ;Routine qui rempli toute la mémoire vidéo texte de 0, afin qu'il n'y aie que des pages vierges ; Entrée : rien ; Sortie : rien ; Modifie :rien _LCDGR_TX_CLMEM: push af push bc push de push hl move #0f,b ; 16 pages textes move #01e0,de ; de = pas d'incrémentation de page move TX_CURRENT_PAGE,hl move hl,GLOBAL_TEMP ; sauve la page en cours move #0000,hl mem0$: move hl,TX_CURRENT_PAGE ; commence par la page du bas call _LCDGR_TX_CLS add de,hl ; ajoute 01E0h à hl dj,ne b,mem0$ ; rempli toutes les pages de 0 move GLOBAL_TEMP,hl move hl,TX_CURRENT_PAGE ; récupère la page en cours call dt2 move #THA,a call _LCDGR_CMD pop hl pop de pop bc pop af ret ; Routine qui affiche une chaîne de caractères sur l'écran graphique ; Requiert d'être en mode texte !!! ; Entrée : - longueur de la chaîne en B, adresse de la chaîne en DE ; Sortie : - rien ; modifie : - A,B,DE _LCDGR_WRSTR: push af move #AWRON,a call _LCDGR_CMD ; Autowrite ON pop af move {de},a ; écrit le texte sub #20,a ; conversion code T6963C call adt inc de dj,ne b,_LCDGR_WRSTR move #AWROFF,a call _LCDGR_CMD ret ; Routine qui lit une chaine de caractère de l'écran LCD et la place en HL ; Entrée : - longueur de la chaîne en BC, adresse de la chaîne en HL ; ; Sortie : - rien ; modifie : - A,BC,HL _LCDGR_RDSTR: stard: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne stard move $SCRDAT,a add #20,a move a,{hl} ; place la donnée lue en mémoire move #0c1,a ; read and increment call _LCDGR_CMD inc hl ; incrémente le pointeur dec bc move b,a or c,a jump,zc stard ; tant qu'on est pas à 0, on lit ret _LCDGR_RDSTR2: move #ARDON,a call _LCDGR_CMD ; Auto Read On lard: call adtr add #20,a ; conversion code T6963C -> ASCII move a,{hl} ; écrit le caractère lu en mémoire inc hl dec bc move b,a or c,a jump,zc lard ; tant que bc <> 0, alors on lit move #ARDOFF,a call _LCDGR_CMD ; Autoread off ret ; Routine qui affiche un caractère sur l'écran graphique et incrémente/décrémente/ne bouge pas le pointeur ; Requiert d'être en mode texte !!! ; Entrée : - caractère en A, commande en B ; Sortie : - rien ; modifie : - A, HL (adapte le pointeur en RAM) _LCDGR_WRCHR: push af ; sauve le caractère ASCII à afficher lchr1: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne lchr1 pop af ; récupère le caractère push af ; et le resauve sub #20,a ; soustrait 20h à A (ASCII -> LCD T6963C) move a,$SCRDAT ; écrit le caractère lchr2: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne lchr2 move b,a move a,$SCRCMD ; écrit la commande (incrément/écrément/ne bouge pas) comp #0c0,a ; write and increment? jump,eq inccurpos comp #0c2,a ; write and decrement? jump,eq deccurpos jump wrend ; la commande sinon est c4 write and nonvariable, le pointeur ne bouge pas, alors on ne modifie rien inccurpos: move TX_CURRENT_POS,hl inc hl move hl,TX_CURRENT_POS jump wrend deccurpos: move TX_CURRENT_POS,hl dec hl move hl,TX_CURRENT_POS wrend: pop af ; et retourne le caractère écrit ret ; même routine que _LCDGR_WRCHR, mais se contente smplement d'écrire sur le LCD sans rien faire d'autre. _LCDGR_WRCHR2: push af ; sauve le caractère ASCII à afficher lch1: move $SCRCMD,A and #3,a comp #3,a ; vérifie les bits de status jump,ne lch1 pop af ; récupère le caractère push af ; et le resauve sub #20,a ; soustrait 20h à A (ASCII -> LCD T6963C) move a,$SCRDAT ; écrit le caractère lch2: move $SCRCMD,a and #3,a comp #3,a ; vérifie les bits de status jump,ne lch2 move b,a move a,$SCRCMD ; écrit la commande (incrément/écrément/ne bouge pas) pop af ret ; Routine qui dessine sur l'écran graphique ; Requiert d'être en mode graphique !!! ; Entrée : - longueur du graphe en BC, adresse du dessin en DE ; Sortie : - rien ; Modifie : - A,BC,DE _LCDGR_WRGRAPH: push af move #AWRON,a call _LCDGR_CMD ; Autowrite ON pop af move {de},a call adt inc de dec bc move b,a comp #0,a jump,ne _LCDGR_WRGRAPH move c,a comp #0,a jump,ne _LCDGR_WRGRAPH move #AWROFF,a ; fin de l'autowrite call _LCDGR_CMD ret ; Routine qui incrémente le curseur ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - A _LCDGR_INCCUR: move CURSOR,hl ; h = y ;l = x move l,a comp #1D,a ; à la dernière colonne ? jump,eq incy ; oui, alors on change de ligne inc a ; sinon on incrémente d'une colonne move a,l jump inccur ; et effectue les modifications sur l'écran incy: move #0,a move a,l ; remet sur la 1ère colonne move h,a comp #0f,a ; au bout de l'écran ? jump,eq curorig ; oui, alors on le remet à l'origine inc a ; augmente d'une colonne move a,h jump inccur ; et effectue les modifications sur l'écran curorig: move #0,a move a,h ; on a replacé le curseur à l'origine en (0;0) inccur: move hl,CURSOR ; sauve les nouvelles coordonnées du curseur call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur ret ; Routine qui décrémente le curseur ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - A _LCDGR_DECCUR: move CURSOR,hl ; h = y ;l = x move l,a comp #0,a ; à la première colonne ? jump,eq decy ; oui, alors on remonte d'une ligne dec a ; sinon on incrémente d'une colonne move a,l jump deccur ; et effectue les modifications sur l'écran decy: move #1d,a move a,l ; remet sur la 30è colonne move h,a comp #0,a ; au haut de l'écran ? jump,eq curend ; oui alors on le met à la fin dec a ; augmente d'une colonne move a,h jump deccur ; et effectue les modifications sur l'écran curend: move #0f,a move a,h ; on a replacé le curseur à l'origine en (0;0) deccur: move hl,CURSOR ; sauve les nouvelles coordonnées du curseur call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur ret ; Routine qui décrémente le pointeur d'adresse ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - HL _LCDGR_GOLEFT: move TX_CURRENT_POS,hl dec l move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD call _LCDGR_DECCUR ; decrémente de curseur ret ; Routine qui incrémente le pointeur d'adresse ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - HL _LCDGR_GORIGHT: move TX_CURRENT_POS,hl inc l move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD call _LCDGR_INCCUR ; incrémente de curseur ret ; Routine qui fait monter d'une ligne le pointeur d'adresse ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - HL _LCDGR_GOTOP: move TX_CURRENT_POS,hl push bc move #0,b move #1e,c ; on va soustraire 30 à hl subc bc,hl ; hl = hl-30 pop bc move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD move CURSOR,hl ; acquiert les coorodonnées du curseur move h,a comp #0,a ; au haut de l'écran ? jump,eq gobot dec a ; non, on remonte d'une ligne move a,h jump gotopend gobot: move #0f,a ; oui, alors on passe tout en bas move a,h gotopend: move hl,CURSOR call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur ret ; Routine qui fait descendre d'une ligne le pointeur d'adresse ; Requiert d'être en mode texte ; Entrée : - rien ; Sortie : - rien ; Modifie : - HL _LCDGR_GOBOTTOM: move TX_CURRENT_POS,hl push bc move #0,b move #1e,c ; on va ajouter 30 à hl add bc,hl ; hl = hl+30 pop bc move hl,TX_CURRENT_POS call dt2 move #ADPSET,a call _LCDGR_CMD move CURSOR,hl ; acquiert les coorodonnées du curseur move h,a comp #0f,a ; en bas de l'écran ? jump,eq gotop inc a ; non, on remonte d'une ligne move a,h jump gobotend gotop: move #0,a ; oui, alors on passe tout en haut move a,h gobotend: move hl,CURSOR call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur ret ; Routine qui affiche un curseur de 1 ligne d'épais ; Entrée : - rien ; Sortie : - rien ; Modifie : - rien _LCDGR_CURSOR1L: push af move #0A0,a call _LCDGR_CMD ; Cusreur 1 ligne pop af ret ; Routine qui affiche un curseur de 8 lignes d'épais ; Entrée : - rien ; Sortie : - rien ; Modifie : - rien _LCDGR_CURSOR8L: push af move #0A7,a call _LCDGR_CMD ; Cusreur 1 ligne pop af ret ; Routine qui efface le caractère pointé par l'adresse suivant celle de la position courrante ; Entrée : - rien ; Sortie : - rien ; Modifie : - rien _LCDGR_DEL: move #20,a ; on écrit un espace move #0c4,b ; datawrite and nonvariable call _LCDGR_WRCHR ; Attention les pointeurs mémoire!! ret ; Routine qui redéfini le text home adress, pour une valeur comprise entre 0000h et 1a39 (valeur maximale pour que le dernier octet de la dernière page texte ; ne soit pas dans la zone mémoire graphique) ; Entrée : - rien ; Sortie : - rien ; Modifie : - TX_CURRENT_POS _LCDGR_PAGEUP: push af push bc push hl ; sauve les registres move TX_CURRENT_PAGE,hl move #01,b move #0e0,c ; bc = 01e0 add bc,hl ; augmente d'une page move h,a comp #1a,a ; > 1Ah? jump,mi pupmax ; oui, alors on met la valeur maximale jump,ne pupend ; si c'est inférieur, alors pas de problème et on termine move l,a ; sinon c'est égal et on va vérifier pour l'octet de poids faible comp #39,a ; > 39h? jump,mi pupmax ; oui, alors on met la valeur maximale jump pupend ; Sinon on est soit égal soit inférieur, donc pas de problèmes pupmax: move #1a,a move a,h move #39,a move a,l pupend: move hl,TX_CURRENT_PAGE ; met à jour la page call dt2 move #THA,a call _LCDGR_CMD move hl,TX_CURRENT_POS ; et le pointeur call dt2 move #ADPSET,a call _LCDGR_CMD move #0,a move a,h move a,l move hl,CURSOR ; place les nouvelles coordonnées du pointeur à l'origine call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur pop hl pop bc pop af ; récupère les registres ret ; Routine qui redéfini le text home adress, pour une valeur comprise entre 0000h et 1a39 (valeur maximale pour que le dernier octet de la dernière page texte ; ne soit pas dans la zone mémoire graphique) ; Entrée : - rien ; Sortie : - rien ; Modifie : - TX_CURRENT_POS _LCDGR_PAGEDOWN: push af push bc push hl ; sauve les registres move TX_CURRENT_PAGE,hl move #01,b move #0e0,c ; bc = 01e0 subc bc,hl ; recule d'une page move h,a comp #00,a ; < 00h? jump,mi pdomin ; oui, alors on met la valeur minimale jump,ne pdoend ; si c'est inférieur, alors pas de problème et on termine move l,a ; sinon c'est égal et on va vérifier pour l'octet de poids faible comp #00,a ; < 00h? jump,mi pdomin ; oui, alors on met la valeur minimale jump pdoend ; Sinon on est soit égal soit inférieur, donc pas de problèmes pdomin: move #0,a move a,h move a,l pdoend: move hl,TX_CURRENT_PAGE ; met à jour la page call dt2 move #THA,a call _LCDGR_CMD move hl,TX_CURRENT_POS ; et le pointeur call dt2 move #ADPSET,a call _LCDGR_CMD move #0,a move a,h move a,l move hl,CURSOR ; place les nouvelles coordonnées du pointeur à l'origine call dt2 move #CURSET,a call _LCDGR_CMD ; bouge le curseur pop hl pop bc pop af ; récupère les registres ret ; Routine qui écrit un caractère dans la CG-RAM ; Entrée : - HL : CG-RAM start address, DE Pointeur du caractère à copier ; Sortie : - rien ; Modifie : - a _LCDGR_WRCG: push bc push de push hl ; sauve les registres call dt2 move #ADPSET,a call _LCDGR_CMD ; défini le pointeur dans la CG-RAM move #AWRON,a call _LCDGR_CMD ; active l'autowrite move #8,b ; un caaractère est stocké sur 8 octets wrexcg: move {de},a ; acquiert la ligne du caractère call adt ; écrit inc hl inc de ; incrémente les pointeurs dj,ne b,wrexcg ; et répète pour les 8 lignes du caractères move #AWROFF,a call _LCDGR_CMD ; désactive l'autowrite move hl,TX_CURRENT_POS ; indique la nouvelle position mémoire pop hl pop de pop bc ; récupère les registres ret ; et l'inscription s'est faite avec succès ;-----------------------------------------------------------+ ; Fin des routines LCD graphique | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routines d'impression sur port Parallèle | ;-----------------------------------------------------------+ ; Initialisation ; retourne en a l'état de réussit de l'initialisation _PARA_PRINTINIT: ; On teste qu'il y aie bien une imprimante.. push af move $PARAFLAG,a ; on stock le flag du port // dans A and #8,a ; SELECT à 1 ? comp #8,a jump,ne _PARA_NOPRINTER ; On initialise l'imprimante move #0,a move a,$PARAINIT ; on réinitialise call _WAIT10ms ; initialisation des paramètres de bases.. move #LONGPRNINIT,bc move #msg_prn_init,hl call _PARA_PRINTSTR ; message de fin, le périphérique est correctement initialisé call _LCDTX_CLS ; efface l'écran move #LONG10,b ; longueur du message move #msg10,hl call _LCDTX_WRSTR call _LCDTX_CR ; on passe à la ligne ; on écrit la 2è ligne du message move #LONG2,b ; longueur du message move #msg2,hl call _LCDTX_WRSTR ; tempo pour lire le message call _WAIT1s call _LCDTX_CLS move #1,a move a,PRINTER_CONNECTED pop af ret _PARA_NOPRINTER: call _LCDTX_CLS move #LONG13,b ; Message pas d'imprimante connectée move #msg13,hl call _LCDTX_WRSTR call _LCDTX_CR move #LONG14,b move #msg14,hl call _LCDTX_WRSTR call _WAIT1s call _LCDTX_CLS move #0,a move a,PRINTER_CONNECTED pop af ret ;========================================= ;========================================= ; écriture d'un bit (caractère ASCII si on imprime) sur le port // ; entrée ; - Caractère en A ; sortie : - rien ; modifie: - A ; BUSY et PAPER ERROR sont actifs HAUT _PARA_PRINTCHR: push af ; Traitement d'erreur en cas d'imprimante occupée.. call _PRINT_BUSY move #0,a comp d,a jump,ne print_chr_error ; Traitement d'erreur en cas d'imprimante non alimentée en papier.. call _PRINT_PAPER move #0,a comp d,a jump,ne print_chr_error ; Traitement d'erreur en cas de message d'erreur de la part de l'imprimante.. call _PRINT_ERROR move #0,a comp d,a jump,ne print_chr_error pop af move a,$PARADATA ; imprime le caractère ;call _WAIT1ms ;call _WAIT1ms ret print_chr_error: nop ret ;========================================= ;========================================= ; écriture d'une chaîne de caractère sur le port // ; entrée ; - Longueur de la chaine de caractères en BC ; - Adresse du début de la chaine en HL ; sortie : - rien ; modifie: - A, D, HL _PARA_PRINTSTR: push bc push hl ; Traitement d'erreur en cas d'imprimante occupée.. parprn: call _WAIT10ms ; temps de pause à déterminer call _WAIT10ms call _PRINT_BUSY move #0,a comp d,a jump,ne print_str_error ; Traitement d'erreur en cas d'imprimante non alimentée en papier.. call _PRINT_PAPER move #0,a comp d,a jump,ne print_str_error ; Traitement d'erreur en cas de message d'erreur de la part de l'imprimante.. call _PRINT_ERROR move #0,a comp d,a jump,ne print_str_error move {hl},a ; acquérir le byte move a,$PARADATA inc hl ; pointage sur le caractère suivant dec bc ; DEC sur 16 bits ne modifie PAS le status FLAG.. ; L'adressage direct de registre 16 bits à 16 bits n'est pas possible ; On compare donc en 2 fois que ça vaille 0.. move b,a or c,a jump,zc parprn ; boucle jusqu'à ce que tous les caractères soient affichés pop hl pop bc ret print_str_error: nop ret ;========================================= ;========================================= ; Vérifie que l'imprimante ne soit pas occupée ; retourne en d l'état de réussite _PRINT_BUSY: push hl push bc move #80,b ; nombre de fois qu'on va attendre au maximum que l'imprimante devienne libre prSta$: call _WAIT1ms ; 1 ms de pause entre chaque lecture du flag busy move $PARAFLAG,a ; on stock le flag du port // dans A and #1,a ; busy? jump,zc n_busy ; si c'est busy on essaie à nouveau, sinon on sort.. dj,ne b,prSta$ call _LCDTX_CLS ; on arrive ici, donc l'imprimante est bien occupée, alors on ne continue pas dans une boucle sans fin. move #LONG8,b ; Message imprimante occupée... move #msg8,hl call _LCDTX_WRSTR call _LCDTX_CR move #LONG11,b move #msg11,hl call _LCDTX_WRSTR move #1,d pop bc pop hl ret n_busy: move #0,d pop bc pop hl ret ;========================================= ;========================================= ; Vérifie que l'imprimante soit toujours alimentée en papier ; retourne en d l'état de réussite _PRINT_PAPER: push hl push bc move $PARAFLAG,a ; on stock le flag du port // dans A and #4,a ; busy? jump,ZS n_pe ; si pas de papier on affiche le message, sinon on sort.. call _LCDTX_CLS move #LONG8,b ; Message plus de papier move #msg8,hl call _LCDTX_WRSTR call _LCDTX_CR move #LONG9,b move #msg9,hl call _LCDTX_WRSTR move #1,d pop bc pop hl ret n_pe: move #0,d pop bc pop hl ret ;========================================= ;========================================= ; Vérifie qu'il n'y aie pas d'erreur gébérique de l'imprimante ; retourne en d l'état de réussite _PRINT_ERROR: push hl push bc move $PARAFLAG,a ; on stock le flag du port // dans A and #10,a ; busy? jump,ZS n_er ; si erreur on affiche le message, sinon on sort.. call _LCDTX_CLS move #LONG8,b ; Message plus de papier move #msg8,hl call _LCDTX_WRSTR call _LCDTX_CR move #LONG12,b move #msg12,hl call _LCDTX_WRSTR move #1,d pop bc pop hl ret n_er: move #0,d pop bc pop hl ret ;-----------------------------------------------------------+ ; Fin des routines d'impression | ;-----------------------------------------------------------+ ;-----------------------------------------------------------+ ; Routines générales d'attente | ; 1 cycle d'horloge = 200 ns à 5 MHz | ; | ; Pour toutes : | ; le call prend 17 cycles | ; Entrée : rien | ; Sortie : rien | ; Modifie : rien | ;-----------------------------------------------------------+ ; Attend en tout 51 cycles soit 10.2 us à 5 MHz _WAIT10_2us: nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles ret ; 10 cycles ; Attend en tout 500 cycles soit 100 us à 5 MHz _WAIT100us: push af ; 11 cycles move #6,a ; 7 cycles j01$: call _WAIT10_2us ; 6*51 cycles = 306 dec a ; 6*4 cycles = 24 jump,zc j01$ ; 5*12 + 1*7 = 67 pop af ; 10 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles ret ; 10 cycles ; Attend en tout 5'000 cycles soit 1 ms à 5 MHz _WAIT1ms: push af ; 11 cycles push bc ; 11 cycles move #9,a ; 7 cycles k01$: call _WAIT100us ; 9*500 cycles = 4'500 push ix ; 9*15 cycles = 135 pop ix ; 9*14 cycles = 126 dec a ; 9*4 cycles = 36 jump,zc k01$ ; 8*12 + 1*7 = 103 nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles nop ; 4 cycles pop bc ; 10 cycles pop af ; 10 cycles ret ; 10 cycles ; Attend en tout 50'000 cycles soit 10 ms à 5 MHz _WAIT10ms: push af ; 11 cycles move #9,a ; 7 cycles l01$: call _WAIT1ms ; 9*5'000 cycles = 45'000 call _WAIT100us ; 9*500 cycles = 4'500 dec a ; 9*4 cycles = 36 jump,zc l01$ ; 8*12 + 1*7 = 103 call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles pop af ; 10 cycles ret ; 10 cycles ; Attend en tout 500'000 cycles soit 100 ms à 5 MHz _WAIT100ms: push af ; 11 cycles move #9,a ; 7 cycles l01$: call _WAIT10ms ; 9*50'000 cycles = 450'000 call _WAIT1ms ; 9*5'000 cycles = 45'000 call _WAIT100us ; 9*500 cycles = 4'500 dec a ; 9*4 cycles = 36 jump,zc l01$ ; 8*12 + 1*7 = 103 call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles pop af ; 10 cycles ret ; 10 cycles ; Attend en tout 5'000'000 de cycles soit 1 s à 5 MHz _WAIT1s: push af ; 11 cycles move #9,a ; 7 cycles l01$: call _WAIT100ms ; 9*500'000 cycles = 4'500'000 call _WAIT10ms ; 9*50'000 cycles = 450'000 call _WAIT1ms ; 9*5'000 cycles = 45'000 call _WAIT100us ; 9*500 cycles = 4'500 dec a ; 9*4 cycles = 36 jump,zc l01$ ; 8*12 + 1*7 = 103 call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles call _WAIT10_2us ; 51 cycles pop af ; 10 cycles ret ; 10 cycles ;-----------------------------------------------------------+ ; Fin de routines | ;-----------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Tables de conversion des scan-codes en codes ASCII | ; Les tables en ROM sont pour le clavier fr-CH | ; on peut bien entendu créer d'autres tables en RAM | ;-------------------------------------------------------------------------------+ ; Pour clavier 102 touches européen ; Par défaut utilise la page ASCII 437 ; Tous sont dans l'ordre des touches si elels peuvent être afectées ; Scan-codes -> ASCII normal _SC2ASCII_N: ; SC, ASCII Signe touche .data.8.8 0E,0F5 ; § 1 .data.8.8 16,31 ; 1 2 .data.8.8 1E,32 ; 2 3 .data.8.8 26,33 ; 3 4 .data.8.8 25,34 ; 4 5 .data.8.8 2E,35 ; 5 6 .data.8.8 36,36 ; 6 7 .data.8.8 3D,37 ; 7 8 .data.8.8 3E,38 ; 8 9 .data.8.8 46,39 ; 9 10 .data.8.8 45,30 ; 0 11 .data.8.8 4E,27 ; ' 12 .data.8.8 55,5E ; ^ 13 ; Il n'y a pas de touche 14 .data.8.8 66,8 ; 15 .data.8.8 0D,9 ; 16 .data.8.8 15,71 ; q 17 .data.8.8 1D,77 ; w 18 .data.8.8 24,65 ; e 19 .data.8.8 2D,72 ; r 20 .data.8.8 2C,74 ; t 21 .data.8.8 35,7A ; z 22 .data.8.8 3C,75 ; u 23 .data.8.8 43,69 ; i 24 .data.8.8 44,6F ; o 25 .data.8.8 4D,70 ; p 26 .data.8.8 54,8A ; è 27 .data.8.8 5B,0F9 ; " 28 ; Il n'y a pas de touche 29 sur le clavier européen 102 touches ; La touche 30 est , son scan-code est 58h .data.8.8 1C,61 ; a 31 .data.8.8 1B,73 ; s 32 .data.8.8 23,64 ; d 33 .data.8.8 2B,66 ; f 34 .data.8.8 34,67 ; g 35 .data.8.8 33,68 ; h 36 .data.8.8 3B,6A ; j 37 .data.8.8 42,6B ; k 38 .data.8.8 4B,6C ; l 39 .data.8.8 4C,82 ; é 40 .data.8.8 52,85 ; à 41 .data.8.8 5D,24 ; $ 42 .data.8.8 5A,10 ; 43 ; La touche 44 est gauche, son scan-code est 12 .data.8.8 61,3C ; < 45 .data.8.8 1A,79 ; y 46 .data.8.8 22,78 ; x 47 .data.8.8 21,63 ; c 48 .data.8.8 2A,76 ; v 49 .data.8.8 32,62 ; b 50 .data.8.8 31,6E ; n 51 .data.8.8 3A,6D ; m 52 .data.8.8 41,2C ; , 53 .data.8.8 49,2E ; . 54 .data.8.8 4A,2D ; - 55 ; La touche 56 n'existe pas ; La touche 57 est droite, son scan-code est 59h ; La touche 58 est gauche, son scan-code est 14h ; La touche 59 n'existe pas ; La touche 60 est gauche, son scan-code est 11h .data.8.8 29,20 ; 61 ; La touche 62 est droite, son scan-code est 2 octets E0h, 11h ; La touche 63 n'existe pas ; La touche 64 est droite, son scan-code est 2 octets E0h, 14h ; Les touches 65 à 74, 77, 78, 82, 87, 88 n'existent pas ; Les touches suivantes (75 à 89) réagissent d'une façon peu commune sur certains claviers ; En effet, elles réagissent à Num Lock et Majuscule ; Si Num Lock est actif et une touche majuscule enfoncée, ou Num-Lock off et aucune touche Majuscule enfoncée alors elles envoient leur Make-code/Brak-code normalement ; Si Num Lock est inactif et Majuscule enfoncée, alors elles désactivent majuscule (droite ou gauche) affichent leur make/break-code puis ré-activent Majuscule ; Si Num Lock est actif et les deux Majuscules relâchés, alors elles activent Majuscule gauche affichent leur make/break-code puis désactivent majuscule gauche ; La touche 75 est , son scan-code est 2 octets E0h, 70h ; La touche 76 est , son scan-code est 2 octets E0h, 71h ; La touche 79 est , son scan-code est 2 octets E0h, 6Bh ; La touche 80 est , son scan-code est 2 octets E0h, 6Ch ; La touche 81 est , son scan-code est 2 octets E0h, 69h ; La touche 83 est , son scan-code est 2 octets E0h, 75h ; La touche 84 est , son scan-code est 2 octets E0h, 72h ; La touche 85 est , son scan-code est 2 octets E0h, 7Dh ; La touche 86 est , son scan-code est 2 octets E0h, 7Ah ; La touche 89 est , son scan-code est 2 octets E0h, 74h ; Touches du pavé numérique, effet différent si celui-ci est "on" ou "off" ; La touche 90 est , son scan-code est 77h ; La touche 91 NUM-LOCK OFF est , son scan-code est 6Ch ; La touche 92 NUM-LOCK OFF est , son scan-code est 6Bh ; La touche 93 NUM-LOCK OFF est , son scan-code est 69h ; Il n'y a pas de touche 94 ; La touche 95 désactive la touche majuscule si elle est enfoncée avant d'envoyer son makre-break-code puis la ré-active .data.8.8 4A,2F ; / 95 ; La touche 96 NUM-LOCK OFF est , son scan-code est 75h ; La touche 97 NUM-LOCK OFF est à ignorer, son scan-code est 73h ; La touche 98 NUM-LOCK OFF est , son scan-code est 72h ; La touche 99 NUM-LOCK OFF est , son scan-code est 70h .data.8.8 7C,2A ; * 100 ; La touche 101 NUM-LOCK OFF est , son scan-code est 7Dh ; La touche 102 NUM-LOCK OFF est , son scan-code est 74h ; La touche 103 NUM-LOCK OFF est , son scan-code est 7Ah ; La touche 104 NUM-LOCK OFF est , son scan-code est 71h .data.8.8 7B,2D ; - 105 .data.8.8 79,2B ; + 106 ; Il n'y a pas de touche 107 .data.8.8 5A,13 ; 108 Avec un E0h devant ; Il n'y a pas de touche 109 ; Si le NUM-LOCK est off, la recherche s'arrête à ce dernier caractère _SC2ASCII_N_NO_KP_END: .data.8.8 76,1B ; 110 ; Ici les touches lorsque qui changent lorsque NUM-LOCK est ON .data.8.8 6C,37 ; 7 91 .data.8.8 6B,34 ; 4 92 .data.8.8 69,31 ; 1 93 .data.8.8 75,38 ; 8 96 .data.8.8 73,35 ; 5 97 .data.8.8 72,32 ; 2 98 .data.8.8 70,30 ; 0 99 .data.8.8 7D,39 ; 9 101 .data.8.8 74,36 ; 6 102 .data.8.8 7A,33 ; 3 103 ; Si le NUM-LOCK est on, la recherche s'arrête à ce dernier caractère _SC2ASCII_N_KP_END: .data.8.8 71,2E ; . 104 ; Informations complémentaires sur les touches restantes ; Il n'y a pas de touche 111 ; La touche 112 est F1, son scan-code est 05h ; La touche 113 est F2, son scan-code est 06h ; La touche 114 est F3, son scan-code est 04h ; La touche 115 est F4, son scan-code est 0Ch ; La touche 116 est F5, son scan-code est 03h ; La touche 117 est F6, son scan-code est 0Bh ; La touche 118 est F7, son scan-code est 83h ; La touche 119 est F8, son scan-code est 0Ah ; La touche 120 est F9, son scan-code est 01h ; La touche 121 est F10, son scan-code est 09h ; La touche 122 est F11, son scan-code est 78h ; La touche 123 est F12, son scan-code est 07h ; La touche 124 est Print Screen / System Require ; Son Make-code/Break-code normal est : E0h, 12h, E0h, 7Ch / E0h, F0h, 7Ch, E0h, F0h, 12h ; Son Make-code/Break-code si CTRL et/ou Maj est actif est : E0h, 7Ch / E0h, F0h, 7Ch ; Son Make-code/Break-code si ALT est actif est : 84h / F0h, 84h ; La touche 125 est , son scan code est 7Eh ; La touche 126 est , elle n'a pas de break-code et son make code est : ; E1h, 14h, 77h, E1h, F0h, 14h, F0h, 77h ; Scan-codes -> ASCII Majuscule ; Touches affectées avec Majuscule actif _SC2ASCII_M: ; SC, ASCII Signe touche .data.8.8 0E,0F8 ; ° 1 .data.8.8 16,2B ; + 2 .data.8.8 1E,22 ; " 3 .data.8.8 26,2A ; * 4 .data.8.8 25,87 ; ç 5 .data.8.8 2E,25 ; % 6 .data.8.8 36,26 ; & 7 .data.8.8 3D,2F ; / 8 .data.8.8 3E,28 ; ( 9 .data.8.8 46,29 ; ) 10 .data.8.8 45,3D ; = 11 .data.8.8 4E,3F ; ? 12 .data.8.8 55,60 ; ` 13 .data.8.8 66,8 ; 15 .data.8.8 0D,9 ; 16 .data.8.8 15,51 ; Q 17 .data.8.8 1D,57 ; W 18 .data.8.8 24,45 ; E 19 .data.8.8 2D,52 ; R 20 .data.8.8 2C,54 ; T 21 .data.8.8 35,5A ; Z 22 .data.8.8 3C,55 ; U 23 .data.8.8 43,49 ; I 24 .data.8.8 44,4F ; O 25 .data.8.8 4D,50 ; P 26 .data.8.8 54,81 ; ü 27 .data.8.8 5B,21 ; ! 28 .data.8.8 1C,41 ; A 31 .data.8.8 1B,53 ; S 32 .data.8.8 23,44 ; D 33 .data.8.8 2B,46 ; F 34 .data.8.8 34,47 ; G 35 .data.8.8 33,48 ; H 36 .data.8.8 3B,4A ; J 37 .data.8.8 42,4B ; K 38 .data.8.8 4B,4C ; L 39 .data.8.8 4C,94 ; ö 40 .data.8.8 52,84 ; ä 41 .data.8.8 5D,9C ; £ 42 .data.8.8 5A,10 ; 43 .data.8.8 61,3E ; > 45 .data.8.8 1A,59 ; Y 46 .data.8.8 22,58 ; X 47 .data.8.8 21,43 ; C 48 .data.8.8 2A,56 ; V 49 .data.8.8 32,42 ; B 50 .data.8.8 31,4E ; N 51 .data.8.8 3A,4D ; M 52 .data.8.8 41,3B ; ; 53 .data.8.8 49,3A ; : 54 .data.8.8 4A,5F ; _ 55 .data.8.8 29,20 ; 61 .data.8.8 4A,2F ; / 95 .data.8.8 7C,2A ; * 100 .data.8.8 7B,2D ; - 105 .data.8.8 79,2B ; + 106 .data.8.8 5A,13 ; 108 Avec un E0h devant _SC2ASCII_M_NO_KP_END: .data.8.8 76,1B ; 110 ; Ici les touches lorsque qui changent lorsque NUM-LOCK est ON .data.8.8 6C,37 ; 7 91 .data.8.8 6B,34 ; 4 92 .data.8.8 69,31 ; 1 93 .data.8.8 75,38 ; 8 96 .data.8.8 73,35 ; 5 97 .data.8.8 72,32 ; 2 98 .data.8.8 70,30 ; 0 99 .data.8.8 7D,39 ; 9 101 .data.8.8 74,36 ; 6 102 .data.8.8 7A,33 ; 3 103 ; Si le NUM-LOCK est on, la recherche s'arrête à ce dernier caractère _SC2ASCII_M_KP_END: .data.8.8 71,2E ; . 104 ; Scan-codes -> ASCII Ctrl + Alt ou Alt Gr ; Touches affectées par ALT GR _SC2ASCII_AGR: ; SC, ASCII Signe touche .data.8.8 16,0DD ; | 2 .data.8.8 1E,40 ; @ 3 .data.8.8 26,23 ; # 4 .data.8.8 25,0F8 ; ° 5 .data.8.8 2E,0F5 ; § 6 .data.8.8 36,0AA ; ¬ 7 .data.8.8 3D,7C ; ¦ 8 .data.8.8 3E,9B ; ¢ 9 .data.8.8 4E,0EF ; ´ 12 .data.8.8 55,7E ; ~ 13 .data.8.8 54,5B ; [ 27 .data.8.8 5B,5D ; ] 28 .data.8.8 52,7B ; { 41 .data.8.8 5D,7D ; } 42 ; La table s'arrête à ce dernier caractère _SC2ASCII_AGR_END: .data.8.8 61,5C ; \ 45 ;-------------------------------------------------------------------------------+ ; Fin des tables | ;-------------------------------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Messages de l'écran LCD alphanumérique | ;-------------------------------------------------------------------------------+ ; Lcd texte msg1: .ascii "LCD display" msg1fin: nop LONG1 = msg1fin-msg1 msg2: .ascii "ready!" msg2fin: nop LONG2 = msg2fin-msg2 msg3: .ascii "Keyboard" msg3fin: nop LONG3 = msg3fin-msg3 msg4: .ascii "init. failed." msg4fin: nop LONG4 = msg4fin-msg4 msg5: .ascii "FS22-647 pOS 0.8" msg5fin: nop LONG5 = msg5fin-msg5 msg6: .ascii "Boot OK" msg6fin: nop LONG6 = msg6fin-msg6 msg7: .ascii "Printer found!" msg7fin: nop LONG7 = msg7fin-msg7 msg8: .ascii "Print failed" msg8fin: nop LONG8 = msg8fin-msg8 msg9: .ascii "Paper error..." msg9fin: nop LONG9 = msg9fin-msg9 msg10: .ascii "Printer" msg10fin: nop LONG10 = msg10fin-msg10 msg11: .ascii "Printer busy..." msg11fin: nop LONG11 = msg11fin-msg11 msg12: .ascii "Printer error..." msg12fin: nop LONG12 = msg12fin-msg12 msg13: .ascii "No printer is" msg13fin: nop LONG13 = msg13fin-msg13 msg14: .ascii "connected" msg14fin: nop LONG14 = msg14fin-msg14 ;-------------------------------------------------------------------------------+ ; Fin des messages du LCD alphanumérique | ;-------------------------------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Messages de l'écran LCD graphique | ;-------------------------------------------------------------------------------+ msgg1: .ascii "- FS22-647 Computer -" msgg1f: nop LONGG1 = msgg1f-msgg1 msgg2: .ascii "CPU is Zilog z80" msgg2f: nop LONGG2 = msgg2f-msgg2 msgg3: .ascii "bytes of RAM available" msgg3f: nop LONGG3 = msgg3f-msgg3 msgg4: .ascii "System ready" msgg4f: nop LONGG4 = msgg4f-msgg4 msgg5: .ascii "Error no keyboard." msgg5f: nop LONGG5 = msgg5f-msgg5 msgg6: .ascii "The system is halted." msgg6f: nop LONGG6 = msgg6f-msgg6 ;-------------------------------------------------------------------------------+ ; Fin des messages du LCD graphique | ;-------------------------------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Caractères à ajouter dans la CG-RAM du LCD graphique | ;-------------------------------------------------------------------------------+ ;§ F5 (donc D5 en CG-RAM, pareil pour les autres attention aux 20h de différence!) CHAR_parag: ;.data.8.8.8.8.8.8.8.8 1C,22,38,24,12,0E,22,1C .data.8.8.8.8.8.8.8.8 1C,22,38,26,32,0E,22,1C ;° F8 CHAR_degre: .data.8.8.8.8.8.8.8.8 08,14,08,00,00,00,00,00 ;¬ AA CHAR_tra: .data.8.8.8.8.8.8.8.8 00,00,00,3E,02,00,00,00 ; " F9 CHAR_umlaut: .data.8.8.8.8.8.8.8.8 14,00,00,00,00,00,00,00 ;| DD CHAR_telque: .data.8.8.8.8.8.8.8.8 08,08,08,08,08,08,08,00 ;à A0 CHAR_aaigu: .data.8.8.8.8.8.8.8.8 04,08,1C,02,1E,22,1E,00 ;ã C6 CHAR_atilde: .data.8.8.8.8.8.8.8.8 12,2C,1C,02,1E,22,1E,00 ;í A1 CHAR_iaigu: .data.8.8.8.8.8.8.8.8 04,08,18,08,08,08,1C,00 ;ó A2 CHAR_oaigu: .data.8.8.8.8.8.8.8.8 04,08,00,1C,22,22,1C,00 ;õ E4 CHAR_otilde: .data.8.8.8.8.8.8.8.8 12,2C,1C,22,22,22,1C,00 ;ú A3 CHAR_uaigu: .data.8.8.8.8.8.8.8.8 04,08,00,24,24,24,1A,00 ;ñ A4 CHAR_ntilde: .data.8.8.8.8.8.8.8.8 12,2C,00,2C,32,22,22,00 ;-------------------------------------------------------------------------------+ ; Fin des caractères dans la CG-RAM du LCD graphique | ;-------------------------------------------------------------------------------+ ;-------------------------------------------------------------------------------+ ; Commandes d'initialisation de l'imprimante | ;-------------------------------------------------------------------------------+ msg_prn_init: .data.8.8.8.8.8.8.8.8.8.8.8 1B,40,1B,31,1B,52,01,07,07,07,07 msg_prn_initfin: nop LONGPRNINIT = msg_prn_initfin-msg_prn_init ; 1B, 40 : Mise à 0 ; 1B, 31 : Interligne 7/60è de pouce ; 1B, 52,1 : Caractères français ; 07 : Cloche ;-------------------------------------------------------------------------------+ ; Fin ds commandes d'initialisation de l'imprimante | ;-------------------------------------------------------------------------------+ ;Avant de programmer l'EPROM, ajouter ici le code de l'image bitmap qui sera affichée au boot. pict1: .data.8.8 55,0AA