; SMILENGHEADER ; COMMENT This is the Smile NG file header, do not modify! ; VERSION 1.0 ; PROC CALM ;-------------------------------------------------------+ ; | ; Petit programme qui imprime avec le port parallèle | ; | ;-------------------------------------------------------+ .PROC z80 .BASE 10'16 jump start ; on va au début du programme ; Définition des constantes .BASE 10'2 ; ========================================= ; CONSTANTES LCD (instructions) ZERO = 0 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 ; Adresses RAM Réservées pour le programme. ; Pages mémoires PAGE0 = 4100 PAGE1 = 4110 PAGE2 = 4120 PAGE3 = 4130 PAGE4 = 4140 PAGE5 = 4150 PAGE6 = 4160 PAGE7 = 4170 PAGE8 = 4180 PAGE9 = 4190 PAGEA = 41A0 PAGEB = 41B0 PAGEC = 41C0 PAGED = 41D0 PAGEE = 41E0 PAGEF = 41F0 ; ========================================= ; Adresses des périphériques ; Adresses MUBUS MUBWR = 0 MUBRD = 10 ; Adresses LCD LCDWRI = 40 LCDWRD = 41 LCDRDI = 42 LCDRDD = 43 ; Adresses PARALLELE PARADATA = 0E0 PARAFLAG = 0E1 PARAINIT = 0E2 ; Adresse du sommet de la pile du soft RAMTOP = 7FFF ;========================================= ; initialisation start: ;création de la pile au sommet de la RAM (évite des bugs avec l'utilisation de zones réservées dans la RAM) ioff ; désactive les interruptions move #RAMTOP,SP ; place le pointeur de pile au sommet de la ram im1 ; met le mode d'interruptions 1 debut: call initlcd ; Initialise l'écran call printinit ; Initialise l'imprimante ; message d'accueil move #LONG1,B ; longueur du message move #msg1,HL call wrstr ; on passe à la ligne call carret ; on écrit la 2è ligne du message d'accueil move #LONG2,B ; longueur du message move #msg2,HL call wrstr ; tempo pour lire le message call tempo_msg call clrscr ;========================================= ; ; PROGRAMME IMPRIMANTE ICI ; ;========================================= ; on écrit sur le LCD que c'est le prot parallèle qui travaille... move #LONG5,B ; longueur du message move #msg5,HL call wrstr ; On imprime le message test move #LONGPRN1,IX move #msg_prn1,HL call print_str ; On boucle sans fin.. endprog: nop jump endprog noprinter: call clrscr move #LONG11,B ; Message pas d'imprimante connectée move #msg11,HL call wrstr call carret move #LONG12,B move #msg12,HL call wrstr jump endprog ;========================================= ; Routines du port parallèle ;========================================= ;========================================= ; Initialisation printinit: ; On teste qu'il y aie bien une imprimante.. move $PARAFLAG,A ; on stock le flag du port // dans A and #8,A ; SELECT à 1 ? comp #8,A jump,ne noprinter ; On initialise l'imprimante move #0,A move A,$PARAINIT ; on réinitialise call attente call attente ; initialisation des paramètres de bases.. move #LONGPRNINIT,IX move #msg_prn_init,HL call print_str ; message de fin, le périphérique est correctement initialisé move #LONG8,B ; longueur du message move #msg8,HL call wrstr ; on passe à la ligne call carret ; on écrit la 2è ligne du message d'accueil move #LONG4,B ; longueur du message move #msg4,HL call wrstr ; tempo pour lire le message call tempo_msg call clrscr ret ;========================================= ;========================================= ; écriture d'un bit (caractère ASCII si on imprime) sur le port // ; entrée ; - Caractère en A ; sortie : - rien ; modifie: - A, HL ; BUSY et PAPER ERROR sont actifs HAUT print_chr: 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 call attente 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 B ; - Adresse du début de la chaine en HL ; sortie : - rien ; modifie: - A, D, HL. IX print_str: ; Traitement d'erreur en cas d'imprimante occupée.. 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 call tempo_print inc HL ; pointage sur le caractère suivant dec IX ; 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 IX,PAGE5 move PAGE5,DE move D,A or E,A jump,ZC print_str ; boucle jusqu'à ce que tous les caractères soient affichés ret print_str_error: nop ret ;========================================= ;========================================= ; Vérifie que l'imprimante ne soit pas occupée print_busy: push HL push BC move $PARAFLAG,A ; on stock le flag du port // dans A and #1,A ; busy? jump,ZC n_busy ; si c'est busy on affiche le message, sinon on sort.. call clrscr move #LONG6,B ; Message imprimante occupée... move #msg6,HL call wrstr call carret move #LONG9,B move #msg9,HL call 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 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 clrscr move #LONG6,B ; Message plus de papier move #msg6,HL call wrstr call carret move #LONG7,B move #msg7,HL call 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 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 clrscr move #LONG6,B ; Message plus de papier move #msg6,HL call wrstr call carret move #LONG10,B move #msg10,HL call wrstr move #1,D pop BC pop HL ret n_er: move #0,D pop BC pop HL ret ;========================================= ;========================================= ;========================================= ;Initialisation de l'écran LCD initlcd: move #ZERO,A move A,$LCDWRI move #FSET,A move A,$LCDWRI call attente call attente call attente call attente call attente call attente call attente call attente call attente call attente move #FSET,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #FSET,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #FSET,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #DISP,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #CLRDSP,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #EMSET,A move A,$LCDWRI call attente call attente ;---------------------------------------------- move #PAHAUT,A move A,$LCDWRI call attente call attente ;---------------------------------------------- ; message de fin, le périphérique est correctement initialisé move #LONG3,B ; longueur du message move #msg3,HL call wrstr ; on passe à la ligne call carret ; on écrit la 2è ligne du message d'accueil move #LONG4,B ; longueur du message move #msg4,HL call wrstr ; tempo pour lire le message call tempo_msg call clrscr ret ;========================================= ;========================================= ; ROUTINES LCD ;========================================= ; 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 waitlcd: 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 wrstr: move {HL},A ; acquérir le byte move A,$LCDWRD ; sortie du caractère sur l'écran call attente call attente inc HL ; pointage sur le caractère suivant dec B jump,ne wrstr ; boucle jusqu'à ce que tous les caractères soient affichés ret ;========================================= ;========================================= ; écriture d'un caractère sur le LCD ; entrée ; - adresse où se trouve le caractère dans HL ; sortie : - rien ; modifie: - A, HL wrchr: call attente call attente move {HL},A move A,$LCDWRD 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: - A, HL rdchr: call attente call attente ; on pointe où on va lire sur l'écran push AF move B,A move A,$LCDWRI pop AF call attente call attente ; 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 rdstr: call attente call attente ; on pointe où on va lire sur l'écran push AF move B,A move A,$LCDWRI pop AF rdstr1$: call attente call attente ; 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 carret: push AF move #PABAS,A move A,$LCDWRI pop AF call attente call attente ret ;========================================= ;========================================= ;Clrear Screen : efface l'écran et repositionne au départ ; entrée : - rien ; sortie : - rien ; modifie : - rien clrscr: push AF move #CLRDSP,A move A,$LCDWRI pop AF call attente call attente ret ;========================================= ;========================================= ;Boucle d'attente ; Nombre de cycles ; call : 17 ; push AF : 11 ; move I,A : 7 ; pop : 10 ; ret : 10 ; 55 ; Boucle (256x) ; dec A : 4 ; jump, cc,I : 10 ; 3584 ; Total : 3639 ; Temps : à 2.5 MHz : 1.4556 ms ; à 5 MHz : 727.8 us attente: push AF move #0FF,A a$: dec A jump,ne a$ pop AF ret ;========================================= ;========================================= ; Temporisation longue, pour avoir le temps de lire le message sur l'écran LCD tempo_msg: push AF move #0FF,A lect1: call attente dec A jump,ne lect1 move #0FF,A lect2: call attente dec A jump,ne lect2 move #0FF,A lect3: call attente dec A jump,ne lect3 pop AF ret ;========================================= ;========================================= ; Temporisation longue, pour laisser le temps à l'imprimante de recevoir tous les bytes tempo_print: push AF move #10,A b$: call attente dec A jump,ne b$ pop AF ret ;========================================= ;========================================= ; messages à afficher ;========================================= ; LCD ; message d'accueil ; page du haut msg1: .ascii "FS22-647 Printer" msg1fin: nop LONG1 = msg1fin-msg1 ; Longuieur de la chaine de caractères ; page du bas msg2: .ascii " Version 0.22 " msg2fin: nop LONG2 = msg2fin-msg2-1 msg3: .ascii "LCD display" msg3fin: nop LONG3 = msg3fin-msg3 msg4: .ascii "ready!" msg4fin: nop LONG4 = msg4fin-msg4 msg5: .ascii "Printer rox =)" msg5fin: nop LONG5 = msg5fin-msg5 msg6: .ascii "Print failed" msg6fin: nop LONG6 = msg6fin-msg6 msg7: .ascii "Paper error..." msg7fin: nop LONG7 = msg7fin-msg7 msg8: .ascii "Printer" msg8fin: nop LONG8 = msg8fin-msg8 msg9: .ascii "Printer busy..." msg9fin: nop LONG9 = msg9fin-msg9 msg10: .ascii "Printer error..." msg10fin: nop LONG10 = msg10fin-msg10 msg11: .ascii "No printer is" msg11fin: nop LONG11 = msg11fin-msg11 msg12: .ascii "connected" msg12fin: nop LONG12 = msg12fin-msg12 ;========================================= ;========================================= ; Imprimante msg_prn1: .data.8.8.8 1B,78,31 ; Style Courrier .ascii "Welcome on Z80 FS22-647 parallel printer !" .data.8 0A ; Passage à la ligne.. .ascii "Comment trouvez-vous? Plut" .data.8 93 ; ô .ascii "t pas mal non?" .data.8 0A .ascii "Enfin, heureux que " .data.8 87 ; ç .ascii "a fonctionne =)" .data.8.8.8.8 0A,0A,1B,34 .ascii "italique " .data.8.8.8.8 1B,35,1B,45 .ascii "gras " .data.8.8.8.8.8 1B,46,1B,2D,31 .ascii "soulign" .data.8.8.8.8.8 82,1B,2D,30,0A .ascii "Ceci est un tr" .data.8 8A .ascii "s long texte sans accents ni rien, " .ascii "qui n'utilise que des caract" .data.8 8A .ascii "res de la page 437 ASCII." .ascii "Je tiens simplement " .data.8 85 .ascii " tester si tous les mots sont imprim" .data.8 82 .ascii "s " .ascii "correctement et si des passages " .data.8 85 .ascii " la lignes automatiques s'effectuent." .data.8 0A msg_prn1fin: nop LONGPRN1 = msg_prn1fin-msg_prn1 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, 30 : Interligne 7/60è de pouce ; 1B'52,1 : Caractères français ;=========================================