PAGE 66,132 TITLE** PROGRAMMA di GESTIONE di programmi ASSEMBLER tipo COM (gennaio 2005) SUBTTL ** TUTORIAL ASSEMBLY -- www.giobe2000.it -- by ing. Giorgio OBER ;/---------------------------------------------------------------------------\ ;| NOME : B3_3Mou1.ASM /--------[RxD da Mouse sotto INT]------------\| ;| AUTORE : Giorgio OBER | ******** Versione con RxD_Int ********* || ;| VERSIONE : gennaio 2005 \------------------[COM1]--------------------/| ;| DESCRIZIONE : Organizza la RICEZIONE di DATI generati ad un Mouse seriale| ;| collegato alla porta (UART) COM1 del computer con la tecnica| ;| dell'interruzione (INTERRUPT); in mancanza di DATI in arrivo| ;| dalla Porta l'esecuzione del programma pu• essere terminata| ;| anche in assenza di movimento o click del Mouse, con la | ;| semplice pressione dei tasti previsti dal menu interno. | ;| | ;|/-----------\ Il collaudo Š stato operato con un MOUSE a 3 pulsanti, in| ;|| 3 | grado di trasmettere alla porta seriale dei pacchetti di 3| ;|| bytes | bytes alla volta, dopo ogni pressione o rilascio dei suoi| ;|\-----------/ pulsanti o dopo lo spostamento del Mouse . | ;| | ;|/-----------\/------------------------------------------------------------\| ;|| ||La Ricezione con tecnica di INTERRUZIONE Š PARTICOLARMNETE|| ;|| ||impegnativa e ma Š la sola PERFETTA e AFFIDABILE;la presenza|| ;|| ||di un capiente Buffer di Ricezione rende asincrona la|| ;|| ||scrittura dei dati ricevuti dal Mouse (esercitata dalla|| ;|| ||di Servizio per la richiesta di INT generata per Dato Pronto|| ;|| ||(ServInt0C) rispetto alla lettura (eseguita da RxD_Int); non|| ;|| NB: ||Š necessario alcun TimeOut e le perdite di tempo per la|| ;|| ||stampa dei caratteri gi… ricevuti e per la verifica della|| ;|| ||pressione di un tasto (per porre termine all'esecuzione del|| ;|| ||programma dopo la ricezione di un Dato), consumate nel MAIN|| ;|| ||PROGRAM, sono ora IRRILEVANTI. || ;|\-----------/\------------------------------------------------------------/| ;| a) versione con presentazione (DESKTOP) | ;| b) NON opera alcun controllo sugli Errori in Ricezione | ;| c) durante la ricezione Š possibile gestire il programma da| ;| tastiera con diversi livelli di menu interattivi. | ;| d) Il protocollo HW impostato per la RICEZIONE SERIALE Š | ;| quello necessario per effettuare il test con MOUSE| ;| collegato sulla porta COM1 (ogni modifica consente ancora| ;| la ricezione, ma con informazioni non decodificabili e | ;| casuali): | ;| /--------------------------------\ | ;| | COM1, 1200, N, 1, 7 | | ;| \--------------------------------/ | ;|/-----------\ Per cambiare PORTA utilizzata dal Mouse Š possibile assegnare| ;|| | al parametro COM_num (qui sotto) un valore diverso; come| ;|| | anticipato non Š invece opportuno (anche se masochisticamente| ;|| | possibile) riassegnare valori diversi ai parametri Baude| ;|| NB: | (Velocit… di ricetrasmissione, fissato a 0060H = 1200 Baude)| ;|| | e Protoc (Protocollo Seriale, fissato a 02H = 7 bit per DATO,| ;|| | 1 bit di stop, nessuna parit…). | ;|| | -------------------------------------------------------------| ;|\-----------/ E' comunque disponibile la versione "B3_3Mou2.ASM" per COM2. | ;| -------------------------------------------------------------| ;| Maggiori dettagli sono disponibili nella sezione dedicata | ;| alla porta seriale sul sito *** http://www.giobe2000.it *** | ;\---------------------------------------------------------------------------/ ;/---------------------------------------------------------------------------\ ;| ;Specificare il Numero di bytes desiderati per ciascuna| Max EQU 3 ;colonna di dati; valori possibili vanno da 1 (un byte| ;| ;per 20 colonne) a 26 (26 bytes per una sola colonna)| ;\---------------------------------------------------------------------------/ _8259ct EQU 20H ;Controller interruzioni 8259, registro di comando _8259mk EQU 21H ;Controller interruzioni 8259, registro di maschera ; --------------------------------------------------------------------------- COM_num EQU 01H ;PORTA utilizzata = COM1 /--------------------------------\ ;EQU 02H ;PORTA utilizzata = COM2 |Scegli la porta COM desiderata | ;EQU 03H ;PORTA utilizzata = COM3 |[ default: programma per COM1 ] | ;EQU 04H ;PORTA utilizzata = COM4 \--------------------------------/ ;---------------------------------------------------------- ;/--------------------------------------------------------\ ;| Scegli la COSTANTE per la VELOCITA` desiderata | ;*--------*-------------------------------*---------------* ;|Costante|********** Baud RATE *********| Errore | ;*--------*-----------------------*-------*---------------* ;EQU 0900H ;|=2304 = (115200/2304) = 50.0 | 50 | ---- | ;EQU 0600H ;|=1536 = (115200/1536) = 75.0 | 75 | ---- | ;EQU 0417H ;|=1047 = (115200/1047) = 110.0 | 110 |(errore 0.026 )| ;EQU 0359H ;|= 857 = (115200/857 ) = 134.4 | 135 |(errore 0.058 )| ;EQU 0300H ;|= 768 = (115200/768 ) = 150.0 | 150 | ---- | ;EQU 0180H ;|= 384 = (115200/384 ) = 300.0 | 300 | ---- | ;EQU 00C0H ;|= 192 = (115200/192 ) = 600.0 | 600 | ---- | Baude EQU 0060H ;|= 96 = (115200/96 ) = 1200.0 | 1200 | ---- | ;EQU 0040H ;|= 64 = (115200/64 ) = 1800.0 | 1800 | ---- | ;EQU 003AH ;|= 58 = (115200/58 ) = 1986.2 | 2000 |(errore 0.69) | ;EQU 0030H ;|= 48 = (115200/48 ) = 2400.0 | 2400 | ---- | ;EQU 0020H ;|= 32 = (115200/32 ) = 3600.0 | 3600 | ---- | ;EQU 0018H ;|= 24 = (115200/24 ) = 4800.0 | 4800 | ---- | ;EQU 0010H ;|= 16 = (115200/16 ) = 7200.0 | 7200 | ---- | ;EQU 000CH ;|= 12 = (115200/12 ) = 9600.0 | 9600 | ---- | ;EQU 0006H ;|= 6 = (115200/6 ) = 19200.0 | 19200 | ---- | ;EQU 0003H ;|= 3 = (115200/3 ) = 38400.0 | 38400 | ---- | ;EQU 0002H ;|= 2 = (115200/2 ) = 57600.0 | 56000 |(errore 2.86) | ;EQU 0001H ;|= 1 = (115200/1 ) =115200.0 |115200 | ---- | ;\--------------------------------*-------*---------------/ ;---------------------------------------------------------- ;/--------------------------------------------------------\ ;| Scegli la COSTANTE associata al PROTOCOLLO SERIALE | ;*---------[7654 3210]=07H--------------------------------* ;| .... ..11 >>>>> 8 bit per il DATO | Protoc EQU 02H ;| default .... ..10 >>>>> 7 bit per il DATO | ;| .... ..01 >>>>> 6 bit per il DATO | ;| .... ..00 >>>>> 5 bit per il DATO | ;*--------------------------------------------------------* ;| .... .1.. >>>>> 2 bit di stop | ;| default .... .0.. >>>>> 1 bit di stop | ;*--------------------------------------------------------* ;| ...0 1... >>>>> parit… dispari | ;| ...1 1... >>>>> parit… pari | ;| default ...x 0... >>>>> nessuna parit… | ;*--------------------------------------------------------* ;| ..0. .... >>>>> parit… disabilitata | ;| .0.. .... >>>>> Break disabilitato | ;| 0... .... >>>>> programmaz. del protocollo | ;\--------------------------------------------------------/ ; MACRO UTILIZZATE DAL PROGRAMMA: include c:\arch-lab\bin\GIOBE.MAC ;/[nuova MACRO locale]------------------------------------------------\ ;|M_Corn Organizza la stampa di una cornice a video, predisponendo i | ;| parametri nei corretti registri, per la procedura RamCorn | ;\--------------------------------------------------------------------/ M_corn MACRO altezza,larghezza,riga,colonna,colore,tipo,ombra,salva MOV AH,altezza ;\[ altezza compresa cornice ] MOV AL,larghezza ;|[ larghezza compresa cornice ] MOV DH,riga ;|[ riga angolo in alto a sinistra ] MOV DL,colonna ;|[ colonna angolo in alto a sinistra ] MOV BL,tipo ;|[ tipo 0=tratto semplice; 1=tratto doppio] MOV BH,ombra ;|[ ombra 0=senza; 1=con ombreggiatura ] MOV CX,salva ;|[ salva RAM in cui salvare l'area coperta ] M_COLOR Colore ;|[ colore: colore della cornice e sfondo ] CALL RamCorn ;/ ENDM ; LIBRERIA UTILIZZATA DAL PROGRAMMA [opzione WinASM altrimenti non necessaria] includelib c:\arch-lab\bin\GIOBE.LIB ;PROCEDURE ESTERNE UTILIZZATE dal PROGRAMMA [NEAR, dalla LIBRERIA ~GIOBE.LIB~] ;----------------------------------------------------------------------------- EXTRN CambiaCol:NEAR EXTRN BIOchr1:NEAR EXTRN RIEMPI:NEAR EXTRN BIOSmsg:NEAR EXTRN SET_cur:NEAR EXTRN STAsp:NEAR EXTRN VIA_cur:NEAR EXTRN RIP_cur:NEAR EXTRN KEYwait:NEAR EXTRN Byt2Asc:NEAR EXTRN Wor2Dec:NEAR EXTRN RamCorn:NEAR ; DICHIARAZIONI (VARIABILI) PER I PROGRAMMI ESTERNI: PUBLIC ATTRIB ;Attributo di colore ; DICHIARAZIONI (PROCEDURE) PER I PROGRAMMI ESTERNI: PUBLIC B3_3Mou1 ;DEFINIZIONE DEL SEGMENTO DEL CODICE ;----------------------------------------------------------------------------- _prog SEGMENT BYTE PUBLIC 'CODE' ASSUME CS:_prog,DS:_prog ORG 0100H INIZIO: JMP B3_3Mou1 ;AREA DESTINATA AI DATI DEL PROGRAMMA ;----------------------------------------------------------------------------- ATTRIB DB 00H Numero DW 0000H Titolo DB "Programmi per il Collaudo della Porta Seriale ",00H Titolo1 DB "COM",00H Tema0 DB "B3_3Mou1 - RICEZIONE da Mouse su COM1" DB " - Protocollo HW: 1200,N,1,7",00H Tema1 DB "NB: La ricezione Š gestita sotto " DB "INTERRUPT con Buffer di Ricezione",00H Nocom0 DB "La PORTA SERIALE desiderata, COM , ",00H Nocom1 DB "non Š",00H Nocom2 DB " disponibile",00H Centro1 DB "Bytes ricevuti dal Mouse",00H MENU01 DB "Inizia",00H MENU02 DB "Quit",00H Mouse DB "Muovi o fai click sul Mouse",00H BytRxD DB "Bytes ricevuti: ",00H NumChar DB 00H ;Numero corrente dei bytes scritti in ogni colonna di dati NumByte DB Max ;Numero di bytes desidetrati per ogni colonna di dati, di ;norma prefissato dal programmatore all'inizio con "EQU" RigCorr DB 2 ;Numero della riga corrente per i bytes ColCorr DB 3 ;Numero della colonna corrente per i bytes Colore DB 1FH ;Colore corrente usato nella stampa dei bytes Dep8259 DB 00H ;Questa variabile tiene copia del contenuto originale del ;Registro di Abilitazione delle Interruzioni [port_9] per ;poterlo ripristinare prima di rimuovere la procedura di ;servizio dell'interruzione IRQ4 Old_Int0C DW 0000H ;Deposito per il Vettore INT 0CH originale attivato dalla DW 0000H ;richiesta d'interruzione dalla porta seriale COM1 ;/---------------------------------------------------------------------------\ ;|Buffer Circolare destinato a raccogliere i dati in arrivo dal Registro Dati| ;|in Ricezione, nelle operazioni di acquisizione sotto Interruzione | ;\---------------------------------------------------------------------------/ ;\Contiene il puntatore alla prima posizione libera ;|del Buffer, cioŠ a quella in cui verr… collocato il ;|Dato Pronto nel Registro di Ricezione; si tratta ;|comunque di un OFFSET rispetto alla prima locazione ;|del Buffer stesso e all'inizio punta la locazione RxDBufWR DW 0000H ;|"RxD_Buf" (offset=0000H); dopo che il dato Š stato ;|collocato nel Buffer (SCRITTURA operata dalla pro- ;|cedura "ServInt0C") il puntatore [RxDBufWR] viene ;|incrementato di UNA posizione e reinizializzato a ;|0000H, se necessario, per ritornare a puntare ;/l'inizio del Buffer ;\Contiene il puntatore al prossimo carattere da ri- ;|muovere dal Buffer Circolare di Ricezione;si tratta ;|comunque di un OFFSET rispetto alla prima locazione ;|del Buffer stesso e all'inizio punta la locazione RxDBufRD DW 0000H ;|"RxD_Buf" (offset=0000H); dopo ogni LETTURA(operata ;|dalla procedura "RxD_Int") il puntatore [RxDBufRD] ;|viene incrementato di UNA posizione e se necessario ;|reinizializzato a 0000H per ritornare a puntare ;/l'inizio del Buffer ;\Per il Buffer Circolare di Ricezione vengono riser- ;|vati 256 bytes; in esso verranno collocati i bytes ;|estratti dal Registro di Ricezione; per la gestione RxD_Buf DB 256 DUP(" ");|del Buffer Circolare vengono utilizzati 2 puntatori DB 00H ;|[RxDBufRD] e [RxDBufWR]: se sono uguali allora il ;|Buffer E` VUOTO; se [RxDBufWR] lo supera di un byte ;/allora Š PIENO RxD_endW LABEL word ;\Identifica la locazione successiva all'ultima RxD_endB EQU this byte ;/prevista per il Buffer Circolare di Ricezione ;AREA DESTINATA ALLE PROCEDURE DEL PROGRAMMA ;/---------------------------------------------------------------------------\ ;| PROCEDURA : BARRA | ;| DESCRIZIONE : Stampa un'intera riga di spazi | ;\---------------------------------------------------------------------------/ BARRA: M_CURSOR DH,0 MOV AL,' ' MOV CX,80 bar0: CALL BIOchr1 LOOP bar0 RET ;/---------------------------------------------------------------------------\ ;| PROCEDURA : DESKTOP | ;| DESCRIZIONE : Predispone il Piano di Lavoro per il Test con Mouse Seriale;| ;| inizializza le Variabili necessarie per il programma di Test| ;| Se il valore ricevuto in ingresso in SI Š 0000H la porta| ;| seriale desiderata NON Š presente nel sistema; la procedura| ;| segnala l'errore e pone automaticamente fine al test,| ;| tornando al DOS (rientro a livello _OUT) con un artificio. | ;\---------------------------------------------------------------------------/ ;/----------------------------------------------\ DESKTOP: ;|Inizializza le variabili - Test Seriale| ;\----------------------------------------------/ PUSH SI ; In ingresso SI=0000 se la porta richiesta NON ; Š presente nel sistema... MOV AL,'°' ;\ M_COLOR 71H ;|Predispone il Piano di gioco su tavola CALL Riempi ;|zigrinata CALL VIA_cur ;/ M_COLOR 70H ;\ MOV DH,0 ;| CALL BARRA ;| M_msgC Titolo, 0,12,70H;| M_COLOR 74H ;|Intestazione M_msgN Titolo1 ;/ MOV DH,24 ;\ CALL BARRA ;|Menu M_msgC MENU02,24,70,70H;| M_Chr 'Q',24,70,74H ;/ ;M_corn altezza,larghezza,riga,colonna,colore,tipo,ombra,salva M_corn 5 , 69 , 9 , 5 , 1EH , 01 , 01 ,1000H POP SI ;\ CMP SI,0000H ;| JNZ DESK_0 ;| M_msgC Nocom0,11,13,1FH;|Recupera il valore iniziale di SI; se vale 0 M_COLOR 9FH ;|la porta richiesta NON Š presente nel sistema; M_msgN Nocom1 ;|se SI contiene 0000 la porta NON Š installata: M_COLOR 1FH ;|si segnala l'errore e si termina senza test M_msgN Nocom2 ;| MOV AL,CS:[depPOR];|"La PORTA SERIALE desiderata, COM , ADD AL,30H ;| non Š disponibile" M_Chr AL,11,45,1EH ;| M_Chr AL, 0,61,74H ;| <<<< Visualizza anche nella barra del Titolo CALL KEYwait ;/ POP AX ;\NB: recupera (con POP AX) la posizione pendente JMP _OUT ;|nello stack dovuta alla chiamata "CALL DESKTOP" ;/per poter tornare con JMP invece che con "RET" ;--------------------------------------------------------------------- DESK_0: M_msgC Tema0,10, 7,1FH;\Messaggio di test eseguibile M_msgC Tema1,12, 7,1FH;| MOV AL,CS:[depPOR];|"RICEZIONE SERIALE su COMx - ADD AL,30H ;| protocollo HW: 9600,N,2,8" M_Chr AL,10,43,1EH ;| M_Chr AL, 0,61,74H ;/ <<<< Visualizza anche nella barra del Titolo M_msgC MENU01,24,7,70H;\/---------------------------------------------\ M_Chr 'I',24, 7,74H ;||************ Primo Menu interno *************| DESK_1: CALL KEYwait ;|\---------------------------------------------/ AND AL,11011111B ;|Rimane in attesa dei tasti del Menu principale: CMP AL,'I' ;| JZ DESK_2 ;| con "I" inizia il Test CMP AL,'Q' ;| con "Q" torna al DOS JNZ DESK_1 ;| JMP _OUT ;/ ;--------------------------------------------------------------------- ;/----------------------------------------------\ ;|Predispone Piano di Lavoro Test Mouse Seriale| ;\----------------------------------------------/ ;M_corn altezza,larghezza,riga,colonna,colore,tipo,ombra,salva DESK_2: M_corn 23 , 80 , 1 , 0 , 03H , 00 , 00 ,2000H MOV CX,5 ;\ MOV DL,14 ;| DESK_3: PUSH CX ;| MOV DH,1 ;| MOV AL,'*' ;| M_CURSOR DH,DL ;| CALL BIOchr1 ;| INC DH ;| MOV AL,'|' ;|Colonne centrali della tabella d'acquisizione MOV CX,21 ;| DESK_4: M_CURSOR DH,DL ;| CALL BIOchr1 ;| INC DH ;| LOOP DESK_4 ;| MOV AL,'*' ;| M_CURSOR DH,DL ;| CALL BIOchr1 ;| ADD DL,13 ;| POP CX ;| LOOP DESK_3 ;/ M_Chr '[', 1,26,03H ;\ M_COLOR 03H ;| Menu M_msgN Centro1 ;| M_COLOR 03H ;| Primo campo di acquisizione Dati seriali MOV AL,']' ;| [Bytes ricevuti] CALL BIOchr1 ;/ M_msgC Mouse,24,3,70H ; "Muovi o fai click sul Mouse" RET ;/---------------------------------------------------------------------------\ ;| PROCEDURA : GoToXY | ;| DESCRIZIONE : Controlla e aggiorna la posizione di stampa corrente al fine| ;| di organizzare la stampa stessa su colonne perallele; per| ;| aumentare la leggibilit… cambia colore dopo ogni pagina. | ;\---------------------------------------------------------------------------/ GoToXY: MOV DH,CS:[RigCorr];\Assume la riga e la colonna di stampa corrente MOV DL,CS:[ColCorr];/ INC DH ;| CMP DH,23 ;|Controllo della Riga corrente˙ JNZ goto2 ;| MOV DH,02 ;/ MOV DL,CS:[ColCorr];\ ADD DL,13 ;| CMP DL,79 ;| JL goto1 ;| MOV DL,03 ;/ MOV CL,CS:[Colore];\ ADD CL,10H ;| TEST CL,80H ;|Controllo del Colore corrente JZ goto0 ;| AND CL,7FH ;|Ricostruisce sfondo BLU OR CL,10H ;| goto0: MOV CS:[Colore],CL;| M_COLOR CL ;/ goto1: MOV CS:[ColCorr],DL;\ goto2: MOV CS:[RigCorr],DH;| CALL SET_cur ;|Fissa la posizione di stampa, stampando subito RET ;/ ;/---------------------------------------------------------------------------\ ;| PROCEDURA : Stampa | ;| DESCRIZIONE : Stampa i dati ricevuti dalla porta SERIALE, organizzandoli a| ;| Max a Max su colonne progressive. | ;\---------------------------------------------------------------------------/ Stampa: PUSH CX PUSH BX PUSH AX INC CS:[Numero] ;*Aggiorna il numero dei Bytes Ricevuti MOV CL,CS:[Colore];* Colore corrente usato nella stampa dei dati MOV CH,CS:[NumByte];\Se Non si tratta del primo dei Max bytes pre- CMP CS:[NumChar],CH;|visti per ogni colonna di dati si prosegue con JNZ stamp0 ;/la stampa degli altri, nella stessa colonna ;\Altrimenti riporta a zero il Numero di bytes MOV Byte Ptr CS:[NumChar],00H;|stampati sulla riga corrente e riporta la po- CALL GoToXY ;|sizione di stampa nel punto pi— opportuno, con ;/il colore corrente stamp0: ;\ INC Byte Ptr CS:[NumChar];|Converte il dato esadecimale presente in AL CALL STAsp ;|nella coppia di caratteri ASCII corrispondenti CALL Byt2Asc ;/[tra due spazi] MOV CH,CS:[NumByte];\Se si tratta dell'ultimo dei Max bytes previ- CMP CS:[NumChar],CH;|sti sulla colonna di dati corrente, stampa uno JNZ stamp1 ;|spazio subito dopo di esso, con il colore cor- CALL STAsp ;/rente M_msgC BytRxD,24,35,70H;\ M_COLOR 74H ;| MOV AX,CS:[Numero];|Stampa e mette a video il numero dei Bytes CALL Wor2Dec ;|ricevuti MOV AL,CS:[Colore];| M_COLOR AL ;/ stamp1: POP AX POP BX POP CX RET ;/---------------------------------------------------------------------------\ ;|PROCEDURA : INIserial | ;|DESCRIZIONE: Seleziona automaticamente la porta seriale COM predisposta dal| ;| valore della costante "COM_num" (per default EQU 01H= COM1), e| ;| se la porta seriale desiderata NON Š presente nel sistema,| ;| lascia in uscita in SI il valore 0000H; altrimenti lascia in| ;| SI l'indirizzo Base dell'UART sotto controllo ([port_8]= 03F8H| ;| o 02F8H o 03E8H o 02E8H) e rende facilmente reperibili TUTTI i| ;| Registri della serie virtualizzandoli con altrettante variabili| ;| /------*-----*-----*-----*-----*-----------------------------\| ;| |******| COM1| COM2| COM3| COM4|Descrizione || ;| *------*-----*-----*-----*-----*-----------------------------*| ;| |port_8|03F8H|02F8H|03E8H|02E8H|Scritt/Lett DATO -LSBdivisore|| ;| |port_9|03F9H|02F9H|03E9H|02E9H|Abilitaz Interruz-MSBdivisore|| ;| |port_A|03FAH|02FAH|03EAH|02EAH|Identif interruzioni || ;| |port_B|03FBH|02FBH|03EBH|02EBH|Registro controllo LINEA || ;| |port_C|03FCH|02FCH|03ECH|02ECH|Registro controllo MODEM || ;| |port_D|03FDH|02FDH|03EDH|02EDH|Registro stato LINEA || ;| |port_E|03FEH|02FEH|03EEH|02EEH|Registro stato del MODEM || ;| \------*-----*-----*-----*-----*-----------------------------/| ;| Inizializza inoltre: | ;| a) la velocit… di ricetrasmissione caricando il divisore a 16| ;| bit, predisposto dalla costante "Baude" (default EQU 000CH=| ;| 9600 baud) nei Registri [port_9]=MSB e [port_8]=LSBdivisore| ;| b) il valore dei parametri desiderati per il protocollo HW, in| ;| in accordo con le scelte suggerite dalla costante "Protoc"| ;| (default EQU 07H= 8 bit di dato e 2 di stop,nessuna parit…)| ;| c) il valore del Registro di abilitazione delle Interruzioni,| ;| [port_9] Š fissato a 00H: in questo modo nessun evento se-| ;| riale produrr… richiesta d'interruzione sulla linea dedica-| ;| ta IRQ3 o IRQ4 e non sar… necessario predisporre la relati-| ;| va procedura di servizio (rispettivamente INT0BH o INT0CH) | ;| d) il valore del Registro di controllo MODEM, [port_C], Š fis-| ;| sato a 03H: in questo modo sono attivi i segnali di tipici| ;| del MODEM, "Data Terminal Ready" e "Request To Send" | ;\---------------------------------------------------------------------------/ depPOR DB COM_num ; Numero della porta COM da controllare (1, 2, 3 o 4) depVEL DW Baude ; Valore n del divisore di Baud RATE necessario per ; stabilire la velocitŕ di Ricetrasmissione = 115200Hz/n depTIP DB Protoc ; Byte ricostruito in accordo con il desiderato ; numero di bit di dato, di stop e di (eventuale) parit… ;/-----*-----*-----*-----*------------------------------\ ;| COM1| COM2| COM3| COM4|Descrizione | ;*-----*-----*-----*-----*------------------------------* port_8 DW ? ;|03F8H|02F8H|03E8H|02E8H|Scritt/Lett DATO - LSBdivisore| port_9 DW ? ;|03F9H|02F9H|03E9H|02E9H|Abilitaz Interruz- MSBdivisore| port_A DW ? ;|03FAH|02FAH|03EAH|02EAH|Identif interruzioni | port_B DW ? ;|03FBH|02FBH|03EBH|02EBH|Registro controllo LINEA | port_C DW ? ;|03FCH|02FCH|03ECH|02ECH|Registro controllo MODEM | port_D DW ? ;|03FDH|02FDH|03EDH|02EDH|Registro stato LINEA | port_E DW ? ;|03FEH|02FEH|03EEH|02EEH|Registro stato del MODEM | ;\-----*-----*-----*-----*------------------------------/ ;---------------------------------------------------------------------------- ;/------[PRIMA FASE]---------------------------------------------------------\ ;| Inizializzazione dei REGISTRI della PORTA SERIALE | ;\---------------------------------------------------------------------------/ INIserial: PUSH ES ;\Assume in AX l'indirizzo BASE della porta MOV AX,0000H ;|seriale suggerita dalla variabile [depPOR], MOV ES,AX ;|a sua volta predisposta con il valore della MOV SI,0400H ;|costante "COM_num" (per default EQU 01H=COM1), MOV AL,CS:[depPOR];|estraendolo dalle locazioni dell'Area di comu- DEC AL ;|nicazione BIOS: le prime sue 8 locazioni sono SHL AL,1 ;|predisposte in fase di bootstrap ai valori: MOV AH,00H ;| /-------------------------------------------\ ADD SI,AX ;| |0000:0400H - Porta Seriale 1 (COM1) 03F8H | MOV AL,ES:[SI] ;| |0000:0402H - Porta Seriale 2 (COM2) 02F8H | INC SI ;| |0000:0404H - Porta Seriale 3 (COM3) 03E8H | MOV AH,ES:[SI] ;| |0000:0406H - Porta Seriale 4 (COM4) 02E8H | POP ES ;| \-------------------------------------------/ ;/se tutte i possibili UART sono presenti... CMP AX,0000H ;\ JNZ INIse_ ;|Se AX contiene 0000 la porta desiderata NON Š MOV SI,AX ;|installata: si torna immediatamente con SI=0 RET ;/ ;--------------------------------------------------------------------- INIse_: MOV CS:[port_8],AX;\ INC AX ;|Altrimenti inizializza le 7 variabili che MOV CS:[port_9],AX;|saranno utilizzate per individuare i Registri INC AX ;|della porta seriale desiderata; per la COM1: MOV CS:[port_A],AX;| INC AX ;|[port_8]=03F8H Registro Scrittura/Lettura DATO MOV CS:[port_B],AX;|[port_9]=03F9H Abilitazione interruzioni INC AX ;|[port_A]=03FAH Identificatore interruzioni MOV CS:[port_C],AX;|[port_B]=03FBH Registro di controllo LINEA INC AX ;|[port_C]=03FCH Registro di controllo MODEM MOV CS:[port_D],AX;|[port_D]=03FDH Registro di stato linea seriale INC AX ;|[port_E]=03FEH Registro stato MODEM MOV CS:[port_E],AX;/ ;/------[SECONDA FASE]-------------------------------------------------------\ ;| Inizializzazione della VELOCITA` di RICETRASMISSIONE SERIALE | ;\---------------------------------------------------------------------------/ ;\/-[port_B]-----------------------------------\ ;|| Registro di controllo della LINEA | ;|\--------------------------------------------/ ;|Inizia la programmazione dell'UART: per poter MOV DX,CS:[port_B];|accedere ai registri divisori di BaudRate Š MOV AL,80H ;|necessario anzitutto porre a "1" il bit7 OUT DX,AL ;|di [port_B]: con questa predisposizione ;|possono ora essere introdotti i corretti ;|valori per il divisore di baud rate: ;| "Baud Rate-lo", su [port_8] e ;/ "Baud Rate-hi", su [port_9] ;\/--------------------------------------------\ ;|| AX= fattore di divisione [115200/costante] | ;|\--------------------------------------------/ ;|Prepara in AX (AL=LSB, AH=MSD) la costante di ;|divisione necessaria per dividere il clock ad ;|alta frequenza (115200Hz) fornito all'UART (a ;|partire dalla frequenza di norma applicata, di ;|1.8432 MHz, LOCALMENTE predivisa per 16) al ;|fine di garantire la desiderata velocit… di ;|RICE-TRASMISSIONE (es: 9600 bps = 9600 baud) ;|/--------------------------------------------\ ;||Il valore del divisore a 16 bit Š suggerito| MOV AX,CS:[DepVEL];||dalla variabile [DepVel], a sua volta predi-| ;||sposta con il valore della costante "Baude"| ;||(default EQU 000CH=9600 baud) | ;|\--------------------------------------------/ ;|Si ricorda che l'UART contiene un generatore ;|programmabile di BAUD RATE in grado di tratta- ;|re qualunque frequenza da 0 a 3.1 MHz; normal- ;|mente la frequenza applicata Š di 1.8432 MHz ;|o, talvolta, quella due terzi pi— grande, ;|3.072 MHz), su cui viene operata immediatamen- ;|te una predivisione per 16, cosicch‚ la co- ;|stante descritta andr… a dividere effettiva- ;|mente la frequenza di 115200 Hz, generando la ;/desiderata frequenza di ricetrasmissione ;\/-[port_8]-----------------------------------\ ;|| Registro divisore Baud RATE (parte bassa) | MOV DX,CS:[port_8];|\--------------------------------------------/ OUT DX,AL ;|Se su [port_B] il bit7="1" la porta [port_8] ;/serve come Registro divisore Baud RATE (low) ;\/-[port_9]-----------------------------------\ MOV AL,AH ;|| Registro divisore Baud RATE (parte alta) | MOV DX,CS:[port_9];|\--------------------------------------------/ OUT DX,AL ;|Se su [port_B] il bit7="1" la porta [port_9] ;/serve come Registro divisore Baud RATE (high) ;/-[NB]----------------------------------------\ ;|se invece su [port_B] il bit7="0" la prima| ;|porta [port_8] serve come BUFFER di trasmis-| ;|sione (in LETTURA) o di ricezione (in SCRIT-| ;|TURA) e la seconda porta [port_9] serve come| ;|Registro di Abilitazione Interruzioni | ;\---------------------------------------------/ ;/------[TERZA FASE]---------------------------------------------------------\ ;| Inizializzazione delle CARATTERISTICHE di RICETRASMISSIONE SERIALE | ;\---------------------------------------------------------------------------/ ;\/-[port_B]-----------------------------------\ ;|| Registro di controllo della LINEA | ;|\--------------------------------------------/ ;|Viene ricostruito il byte da spedire alla por- ;|ta [port_B], che rappresenta le caratteristi- ;|che desiderate, cioŠ il Numero di bit per DATO ;|il Numero di bit di STOP e la presenza del Bit ;|di Parit…; poich‚ la programmazione della ;|velocit… di RICETRASMISSIONE Š gi… stata ;|eseguita Š necessario anche riporre a "0" il ;|bit7 di tale byte;di norma si pone a "0" anche ;|il bit6 (se ="1", impostazione di break, il ;|dato di output seriale Š forzato alla condi- ;|zione di SPACE (0 logico) indipendentemente da ;|ci• che l'UART intende trasmettere) e il bit5 ;|(se = "1" il bit di parit… viene forzato ad un ;|valore costante, in funzione della programma- ;|zione dei bit4/bit3; altrimenti il bit di ;|parit… conserva il suo significato) ;|/--------------------------------------------\ ;||La combinazione di bit corrispondente alle| MOV DX,CS:[port_B];||nostre esigenze Š suggerita dalla variabile| MOV AL,CS:[DepTIP];||[DepTip], a sua volta predisposta con il va-| OUT DX,AL ;||lore della costante "Protoc" (default EQU 07| ;||= 8 bit di dato e 2 di stop, nessuna parit…)| ;|\--------------------------------------------/ ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[port_B]| 0 | 0 | 0 | x | 0 | 1 | 1 | 1 | 07H ;| \---*---*---*---*---*---*---*---/ ;|Protocollo/ | | | | | \---*-8 dato ;|Break disab.--/ | | | \-----2 bit stop ;/Parit… disab.-----/ \---*-----nessuna parit… ;/------[QUARTA FASE]--------------------------------------------------------\ ;| Inizializzazione del REGISTRO di CONTROLLO del MODEM | ;\---------------------------------------------------------------------------/ ;\/-[port_C]-----------------------------------\ ;|| Registro di controllo del MODEM | ;|\--------------------------------------------/ ;|Normalmente il Registro di MODEM va inizializ- ;|zato a 03H e poi non si tocca pi—; tale predi- ;|sposizione bit0 e bit1 a "1") attiva i segnali ;|di controllo tipici del MODEM, "Data Terminal ;|Ready" e "Request To Send": in questo modo il ;|il computer DTE (UART) avvisa il modem DCE che ;|Š regolarmente collegato alla linea di comuni- ;|cazione, che Š pronto a trasmettere o ricevere ;|dati (DTR) e che dispone di dati ed č pronto a ;|trasmetterglieli (RTS): il bit2 OUT1 di questo ;|registro (uscita ausiliaria destinata utente) ;|non Š usato, mentre il bit3 (OUT2=altra uscita ;|ausiliaria destinata utente) DEVE essere posta MOV DX,CS:[port_C];|a "1" solo se si desidera consentire al- MOV AL,03H ;|l'INTERRUZIONE generata dall'UART di raggiun- OUT DX,AL ;|gere il bus del sistema (per essere eventual- ;|mente controllata dal gestore delle interru- ;|zioni, 8259); infine il bit4 deve essere a 0, ;|in condizioni normali; se forzato a 1 la porta ;|seriale (UART) si pone in uno stato molto par- ;|ticolare, LookBack Mode, straordinariamente ;|utile per collaudare i nostri programmi ma del ;|tutto inopportuno in regolare ricetrasmissione ;|i bit5, bit6 e bit7 sono sempre a 0 (non usati ;|da nessuna versione di UART) ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[port_C]| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 03H ;| \---*---*---*---*---*---*---*---/ ;|non usati-*---*---/ | | | | \DTR on ;|no LookBack Mode------/ | | \----RTS on ;/INT disabilitate----OUT2--/ \OUT1-non usata ;/------[QUINTA FASE]--------------------------------------------------------\ ;| Inizializzazione di ABILITAZIONE delle INTERRUZIONI SERIALI | ;\---------------------------------------------------------------------------/ ;\/-[port_9]-----------------------------------\ ;|| Registro di abilitazione delle INTERRUZIONI| ;|\--------------------------------------------/ ;|Vengono specificati solo gli eventi che si ;|desidera utilizzare per innescare il meccani- ;|smo dell'interruzione, in grado di attivare la ;|linea IRQ3/IRQ4 dedicata all'UART coinvolto, ;|avvisando cosŤ il controllore delle interru- ;|zioni 8259 che far… partire la relativa proce- ;|dura di servizio BIOS, INT 0BH o INT 0CH; se ;|NON SI DESIDERA far riferimento alle tecniche ;|d'interruzione tutti i bit di questo registro ;|sono lasciati a 0; altrimenti i bit significa- MOV DX,CS:[port_9];|tivi sono: bit0="1" abilita interrupt quando MOV AL,00H ;|c'Š un DATO PRONTO in RICEZIONE; bit1="1" abi- OUT DX,AL ;|lita interrupt quando il registro di TRASMIS- RET ;|SIONE Š VUOTO (DATO TRASMESSO); il bit2="1" ;|abilita interrupt se il registro di stato non ;|Š pi— a 00H (ERRORI in RICEZIONE o RICEVUTA ;|condizione di BREAK); il bit3="1" abilita un ;|interrupt per cambiamento dello stato del ;|MODEM. Se su [port_B] il bit7="0" la porta ;|[port_9] serve come Registro di Abilitazione ;|delle Interruzioni: con i bit7öbit4 tutti a ;|"0" tutte le interruzioni da parte della ;|SERIALE sono disabilitate ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[port_9]| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00H ;| \---*---*---*---*-no*-no*-no*-no/ ;|non usati-*---*---*---/ | | | | RxD ;|Variazione Stato Linea----/ | | \-pieno ;/Variazione Registro Modem-----/ \-TxD vuoto ;/---------------------------------------------------------------------------\ ;| /----------------------------------------------\| ;|PROCEDURA : ServInt0C |** VERSIONE per IRQ4 da Dato Ricevuto Pronto *|| ;| \----------------------------------------------/| ;|DESCRIZIONE: Procedura di servizio in risposta all'attivazione della linea| ;| d'interruzione IRQ4 generata da uno dei numerosi eventi| ;| seriali associati alla porta COM1. | ;|/-----------\ | ;|| | Questa versione provvede SOLO al servizio delle interruzioni| ;|| | generate da "Dato Pronto in Registro di Ricezione" ma dispone| ;|| | del codice necessario a soddisfare anche le richieste dovute| ;|| | a "Registro di Trasmissione Vuoto"; negli altri 2 casi| ;|| | (variazione dei 2 Registri di Stato, della Linea e del Modem)| ;|| | si limita ad azzerare la richiesta dell'interruzione senza| ;|| NB: | provvedere a nessun altro servizio. | ;|| | In ogni caso ciascuno dei possibili eventi seriali dovr…| ;|| | essere autorizzato ad interrompere fissando a 1 SOLO i bit ad| ;|| | essi relativi nel "Registro di Abilitazione Interruzioni",| ;|| | [port_9]), operata sulla riga di programma con l'etichetta| ;|| | "Cambia", dentro la Procedura "SetInt0C" (vedi sotto). | ;|\-----------/ | ;\---------------------------------------------------------------------------/ ServINT0C: PUSH AX PUSH BX PUSH DX Riprova:MOV DX,CS:[port_A];\/76543*210\ <<<< bit di [port_A] ;|| |XX1|Nessuna richiesta di INT pendente ;|| |110|Variazione Registro Stato Linea ;|| |100|Dato pronto in Ricezione ;|| |010|Trasmettitore vuoto ;|| |000|Variazione Registro Stato Modem ;|\-----*---/ IN AL,DX ;|Controlla il bit0 del Registro di Identifica- TEST AL,00000001B ;|zione Interrupt, [port_A] e, se Š 1, significa JZ Chk_Int ;|che nessuna interruzione risulta pendente: la ;/procedura di servizio viene subito terminata!! ; /--------------------------------------------------------------------\ ; |Uscita dal Servizio d'Interruzione richiesto dalla porta seriale | ; |--------------------------------------------------------------------| ; |Non ci sono pi— richieste pendenti; ogni procedura di "servizio IRQ"| ; |come questa deve segnalare la sua fine spedendo il Controller delle| ; |Interruzioni del computer (PIC 8259A) il codice "EOI" (End Of Inter-| ; |rupt) per azzerarlo, in vista delle prossime interruzioni. | ; \--------------------------------------------------------------------/ MOV AL,20H ;\Segnala al Registro di Comando del Controller OUT _8259ct,AL ;|Interruzioni 8259A la fine della procedura di ;/servizio INT spedendo 20H,EOI,End Of Interrupt ;\Di norma al termine della procedura di servi- ;|zio di una INTERRUZIONE deve essere riabilita- ;STI ;|ta la possibilit… di interrompere la CPU in ;|modo MASCHERABILE da parte delle periferiche ;/autorizzate, con l'istruzione "STI" POP DX ;Ritorna dall'interruzione POP BX POP AX IRET ;----------------------------------------------------------------------------- ;\NB: la successiva verifica dei 2 bit di ID ha ;|ovviamente senso solo se la Procedura SetInt0C Chk_Int:AND AL,00000111B ;|ha autorizzato il possibile evento seriale ad ;|interrompere il processore, cioŠ SOLO se i ;|relativi bit del Registro di Abilitazione ;/Interruzioni, [port_9], sono stati fissati a 1 CMP AL,00000100B ;\Interrupt per Dato Pronto in Ricezione JE RxD_WR ;|... vai al Servizio CMP AL,00000010B ;|Interrupt per Trasmettitore Vuoto JE TxD_RD ;|... vai al Servizio CMP AL,00000110B ;|Interrupt per Variazione Registro Stato Linea JE StatLin ;/... vai al Servizio ; /--------------------------------------------------------------------\ ; |Servizio per Variazione Registro Stato Modem | ; |--------------------------------------------------------------------| ; |In uscita dalla precedente verifica non pu• che essere AL=00000000B;| ; |comunque questo codice non dovrebbe mai essere eseguito, dato che| ; |l'evento che dovrebbe richiederlo NON Š stato abilitato ad interrom-| ; |pere; il servizio assicurato, nel caso di Variazione del Registro di| ; |Stato del Modem, consiste nella lettura del registro stesso, opera-| ; |zione che azzera tutte le interruzioni pendenti da esso dipendenti. | ; |Se fosse abilitata il Servizio sarebbe attivato dopo ogni variazione| ; |dei segnali in arrivo, come CD (Carrier Detect, Ring Indicator (RI),| ; |Data Set Ready (DSR) e Clear To Send (CTS) | ; \--------------------------------------------------------------------/ StatMod:MOV DX,CS:[port_E];\La lettura del Registro di Stato del Modem, IN AL,DX ;|[port_E], annulla tutti i bit in esso contenu- JMP Riprova ;|ti, annullando cosŤ anche le possibili richie- ;|ste d'interruzione pendenti per presenza di ;/CTS, DSR o RI ; /--------------------------------------------------------------------\ ; |Servizio per Variazione Registro Stato Linea | ; |--------------------------------------------------------------------| ; |Comunque questo codice non dovrebbe mai essere eseguito, dato che| ; |l'evento che dovrebbe richiederlo NON Š stato abilitato ad interrom-| ; |pere; il servizio assicurato, nel caso di Variazione del Registro di| ; |Stato della Linea consiste nella lettura del registro stesso, opera-| ; |zione che azzera tutte le interruzioni pendenti da esso dipendenti. | ; |Se fosse abilitata il Servizio sarebbe attivato se, durante la| ; |ricezione di dati fosse stata rilevata la presenza di errori (di| ; |sovrapposizione, di parit… o di composizione) o la presenza di un| ; |segnale di break | ; \--------------------------------------------------------------------/ StatLin:MOV DX,CS:[port_D];\La lettura del Registro di Stato della Linea, IN AL,DX ;|[port_D], annulla tutti i bit in esso contenu- JMP Riprova ;|ti, annullando cosŤ anche le possibili richie- ;|ste d'interruzione pendenti per errori in ;/ricezione o per presenza di segnale di Break ; /--------------------------------------------------------------------\ ; |Servizio per Dato Pronto in Ricezione (per "SCRIVERE" il Buffer RxD)| ; |--------------------------------------------------------------------| ; |Questo Servizio assume il Dato Pronto dal Registro di Ricezione e lo| ; |inserisce nella prima locazione libera del Buffer Circolare di| ; |Ricezione; naturalmente viene garantita la circolarit… del Buffer,| ; |lasciando aggiornato il puntatore [RxDBufWR] di scrittura (cioŠ| ; |incrementandolo di 1 dopo l'aggiunta del byte), in modo da puntare| ; |sempre la successiva locazione disponibile ad ospitare l'eventuale| ; |successivo Dato Pronto; se necessario [RxDBufWR] viene reinizializ-| ; |zato per tornare a puntare l'inizio del Buffer, tenendo presente che| ; |esso Š in realt… un offset riferito all'inizio del Buffer, cioŠ (nel| ; |nostro caso) di valore compreso tra 0 e 255. | ; |La lettura dei bytes del Buffer Circolare di Ricezione Š esercitata| ; |da una procedura dedicata, "RxD_Int", dotata del proprio puntatore| ; |[RxDBufRD] di lettura. | ; |Durante la Gestione del Dato Pronto (operazione critica) si deve| ; |essere certi che le interruzioni siano disabilitate, cosa di solito| ; |assicurata per default dalle normali procedure di servizio delle INT| ; \--------------------------------------------------------------------/ RxD_WR: MOV DX,CS:[port_8];\Legge il Dato Pronto dal Registro di Ricezione IN AL,DX ;/ ;/---------------------------------------------\ ;| SCRITTURA nel Buffer Circolare di Ricezione | ;\---------------------------------------------/ MOV BX,CS:[RxDBufWR];\Predispone in BX il puntatore alla prima loca- MOV CS:[RxD_Buf+BX],AL;|zione del Buffer disponibile a ricevere nuovi ;|bytes e vi inserisce il Dato Pronto appena ;/letto dal Registro di Ricezione, [port_8] ;\Predispone il puntatore di SCRITTURA alla lo- INC BX ;|cazione successiva del Buffer (la prima dispo- CMP BX,256 ;|nibile a ricevere il prossimo carattere) e se JC RxD_W1 ;|viene a coincidere con la fine fisica del MOV BX,0000H ;|Buffer, esso viene reinizializzato a 0000H per ;/garantire la circolarit… ;\Se per qualche ragione la procedura di LETTURA ;|"RxD_Int", non Š stata in grado di "scaricare" ;|i bytes del Buffer [cosa molto improbabile se ;|la lettura viene esercitata regolarmente] i 2 RxD_W1: CMP BX,CS:[RxDBufRD];|puntatori del Buffer Circolare di Ricezione JZ RxD_W2 ;|coincidono indicando che il Buffer Š PIENO: in ;|questo caso il carattere appena letto viene ;/perduto (non essendoci per esso pi— spazio) ;\Comunque, prima di tornare il valore del nuovo MOV CS:[RxDBufWR],BX;|puntatore viene memorizzato nella variabile ad ;/esso dedicata RxD_W2: JMP Riprova ; Torna in attesa di altri interrupts seriali ; /--------------------------------------------------------------------\ ; |Servizio per Trasmettitore Vuoto (per "LEGGERE" il Buffer TxD)| ; |--------------------------------------------------------------------| ; |Questo Servizio Š attivato in risposta alla richiesta d'Interruzione| ; |per "Registro di Trasmissione Vuoto" cioŠ quando l'UART Š in attesa| ; |di dati da spedire sulla linea seriale; dato che l'evento che| ; |dovrebbe richiederlo NON Š stato abilitato ad interrompere questo| ; |codice non dovrebbe mai essere eseguito. | ; \--------------------------------------------------------------------/ TxD_RD: JMP Riprova ;/---------------------------------------------------------------------------\ ;| /--------------------------------------------------\| ;|PROCEDURA : RxD_Int |****************** Versione 05 ****************** || ;| |(per "SCARICARE" il Buffer Circolare di Ricezione)|| ;| \--------------------------------------------------/| ;|DESCRIZIONE : Questa procedura assume un byte dal Buffer Circolare di Rice-| ;| zione, lasciandolo in uscita in AL, con AH=00H; se nel Buffer| ;| non ci sono valori utilizzabili si torna comunque al program-| ;| chiamante, con AH=01H, per sottolineare che il dato in AL non| ;| Š attendibile ed Š necessario attendere che la porta seriale| ;| segnali la Ricezione di un Dato Pronto e la procedura di| ;| Servizio delle Interruzioni Seriali INT 0CH, "ServInt0C", con| ;| l'aiuto del proprio puntatore [RxDBufWR] di scrittura,| ;| provveda ad inserirlo nel Buffer stesso. | ;|/-----------\ | ;|| | La scelta di affidare ad AH l'attendibilit… del dato ricevuto| ;|| | consente a questa procedura di tornare comunque al programma| ;|| NB: | chiamante, permetendogli la discrezionalit… di rientrare in| ;|| | attesa di dati dalla seriale o di porre termine a se stesso. | ;|\-----------/ | ;| Naturalmente viene garantita la circolarit… del Buffer| ;| controllando anzitutto se il puntatore al primo carattere da| ;| leggere, [RxDBufRD], coincide con il puntatore alla locazione| ;| in cui mettere il prossimo carattere, [RxDBufWR], (in questo| ;| caso il Buffer Circolare Š VUOTO) e incrementando [RxDBufRD]| ;| di 1 dopo l'aggiunta del byte, in modo da puntare sempre la| ;| locazione successiva; se necessario [RxDBufRD] viene reini-| ;| zializzato per tornare a puntare l'inizio del Buffer, tenendo| ;| presente che esso in realt… Š un offset riferito all'inizio | ;| del Buffer, nel nostro caso di valore compreso tra 0 e 255. | ;\---------------------------------------------------------------------------/ RxD_Int: ;\In questa fase si confrontano i puntatori tra ;|loro; per evitare che vengano inseriti nuovi PUSH BX ;|Dati Pronti in Ricezione mentre si sta prele- CLI ;|vando un byte dalla coda, cioŠ per evitare che ;|cambi il puntatore [RxDBufWR], le interruzioni ;/mascherabili sono disabilitate MOV BX,CS:[RxDBufRD];\Se [RxDBufWR] NON Š uguale a [RxDBufRD] il CMP BX,CS:[RxDBufWR];|Buffer contiene nuovi Dati Pronti Ricevuti; si JNZ RxD500 ;/provvede al loro prelievo STI ;\Se invece [RxDBufWR] Š uguale a [RxDBufRD] il POP BX ;|Buffer Š VUOTO, cioŠ non Š stato rilevato MOV AH,01H ;|alcun Nuovo Dato Ricevuto: si rimane torna con RET ;/AH = 01 ;/---------------------------------------------\ ;| LETTURA del Buffer Circolare di Ricezione | ;\---------------------------------------------/ ;\La disabilitazione delle interrruzioni masche- ;|rabili, ancora in atto, consente di prelevare RxD500: MOV AL,CS:[RxD_Buf+BX];|il dato dalla coda senza correre il rischio di ;|subire una contemporanea scrittura da parte ;/della procedura di servizio INT 0CH, ServInt0C INC BX ;\Il puntatore al primo carattere da LEGGERE CMP BX,256 ;|viene incrementato e se viene a coincidere con JC RxD501 ;|la fine fisica del Buffer esso viene reinizia- MOV BX,0000H ;/lizzato a 0000H per garantire la circolarit… RxD501: MOV CS:[RxDBufRD],BX;\Prima di tornare il valore del nuovo puntatore STI ;|viene memorizzato nella variabile ad esso POP BX ;|dedicata e si lascia AH=00H per indicare che MOV AH,00H ;|il Dato in AL Š utilizzabile RET ;/ ;/---------------------------------------------------------------------------\ ;| /----------------------------------------------\| ;|PROCEDURA : SetInt0C |** VERSIONE per IRQ4 da Dato Ricevuto Pronto *|| ;| \----------------------------------------------/| ;|DESCRIZIONE: Questa procedura predispone il computer per accettare le| ;| richieste d'interruzione generate dalla porta seriale COM1. | ;|/-----------\ | ;|| | Questa versione abilita la richiesta di interruzione SOLO in| ;|| NB: | caso di "Dato pronto" nel Ricevitore; ogni eventuale modifica| ;|| | va operata sulla riga di programma con l'etichetta: "Cambia".| ;|\-----------/ | ;| Per rendere disponibile una procedura di servizio per le| ;| richieste d'interruzione generate dalla porta seriale COM1 Š| ;| necessario rimappare il vettore INT 0CH chiamato a puntarla;| ;| per poter ripristinare in uscita le stesse condizioni trovate| ;| in ingresso, prima di sostituirlo, salva il valore del vettore| ;| originale. | ;| Interviene sia sui registri dell'UART (azzerando le richieste| ;| d'interruzione pendenti e abilitando solo gli eventi seriali| ;| autorizzati a interrompere, nel nostro esempio dal ricevitore| ;| e dal trasmettitore) che sul controller delle interruzioni del| ;| computer (il PIC 8259A). | ;| Sebbene sia cosa consiglibile la procedura non provvede al| ;| servizio di errori critici e di break: in queste condizioni la| ;| pressione dei tasti ctrl-C o ctrl-Break imporrŕ un ritorno al| ;| DOS senza ripristinare il vettore INT 0CH originale. | ;\---------------------------------------------------------------------------/ SetInt0C: ;\La sostituzione di un Vettore Š operazione CLI ;|critica, per cui per tutto il tempo necessario ;/le interruzioni sono disabilitate PUSH ES ;\ XOR AX,AX ;| MOV ES,AX ;| MOV DI,0030H ;|Punta con ES:DI la locazione 0000:0030H, LEA SI,Old_Int0C ;|contenente il vettore originale INT 0CH per il MOV AX,ES:[DI] ;|servizio dell'interruzione IRQ4 da COM1 o COM3 MOV CS:[SI],AX ;|e con CS:SI la variabile locale [Old_Int0C], ADD DI,2 ;|nella quale riporne il valore, in attesa di ADD SI,2 ;|ripristinarlo, alla fine del programma MOV AX,ES:[DI] ;| MOV CS:[SI],AX ;/ MOV AX,CS ;\Sostituisce nelle medesime locazioni della MOV ES:[DI],AX ;|Tabella dei Vettori (i 4 bytes a partire da SUB DI,2 ;|0000:0030H ancora puntati da ES:DI) il vettore LEA AX,ServInt0C ;|originale INT 0CH con CS:ServInt0C, indirizzo MOV ES:[DI],AX ;|del nuovo servizio per l'interuzione IRQ4 da POP ES ;/COM1 o COM3 ;\La lettura dei 2 Registri di Stato dell'UART MOV DX,CS:[port_D];|(quello di Linea, [port_D] e quello del Modem, IN AL,DX ;|[port_E]) annulla tutti i bit in essi contenu- MOV DX,CS:[port_E];|ti, annullando cosŤ anche le possibili richie- IN AL,DX ;|ste d'interruzione pendenti per errori in ;/ricezione o per presenza di CTS, DSR o RI MOV DX,CS:[port_A];\La lettura del Registro Identificatore di IN AL,DX ;|Interrupt, [port_A], annulla anche l'eventuale ;/suo bit0 (se bit0=1 significa INT pendente) MOV DX,CS:[port_8];\La lettura del Registro di Ricetrasmissione, IN AL,DX ;|[port_8], annulla l'eventuale richiesta di ;/interrupt per "dato seriale disponibile" ;\Per poter abilitare con sicurezza gli eventi MOV DX,CS:[port_B];|seriali autorizzati ad interrompere č necessa- IN AL,DX ;|rio essere certi che l'indirizzo [port_9] stia AND AL,01111111B ;|puntando il Registro di Abilitazione delle OUT DX,AL ;|Interruzioni e NON uno dei 2 Registri Divisori ;|di Baud Rate, ponendo a 0 il bit7 del Registro ;/di Controllo Linea, [port_B] ; ;\Stabilisce gli eventi seriali autorizzati a ; ;|richiedere servizio d'interruzione, ponendo a ; NB: cambia qui gli eventi ;|1 i bit ad essi associati, nel Registro di ; che possono interrompere.. ;|Abilitazione delle Interruzioni, [port_9]: ; |||| ;| /-7-6-5-4-*-3-*-2-*-1-*-0-\ Cambia: MOV AL,00000001B ;|[port_9]| 0 0 0 0 | 0 | 0 | 0 | 1 | 01H MOV DX,CS:[port_9];| \---------*-no*-no*-no*-si/ OUT DX,AL ;|Variaz. Stato Linea-/ | | \- Dato pronto ; ;|Variaz. Stato Modem-----/ | in Ricezione ; ;|Dato trasmesso,Trasm. vuoto-/ ; ;|I bit degli eventi non autorizzati ad inter- ; ;/rompere DEVONO essere lascati a 0 logico ;\Per poter rendere possibili le interruzioni da ;|parte dell'UART Š necessario forzare a 1 la ;|linea OUT2 (pin31 UART); questa situazione si ;|ottiene portando a 1 il bit3 del Registro di ;|Controllo Modem, [port_C] e permette il colle- MOV AL,00001011B ;|gamento a livello hardware della linea INTR MOV DX,CS:[port_C];|(pin30 dell'UART) alla linea IRQ4 del control- OUT DX,AL ;|ler delle interruzioni, 8259A; in condizioni ;|normali anche le linee DTR (pin33 UART) e RTS ;|(pin32 UART) devono essere attive (cioŠ a 1) ;|per cui saranno a 1 anche i rispettivi bit0 ;|e bit1, mentre il bit4 (Lookback Mode) deve ;|essere ovviamente a 0 ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[port_C]| 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0BH ;| \---*---*---*---*---*---*---*---/ ;|non usati-*---*---/ | | | | \DTR on ;|no LookBack Mode------/ | | \----RTS on ;/INT abilitate ----OUT2--/ \OUT1-non usata ;\Non rimane ora che intervenire sul controller ;|delle interruzioni del computer (il PIC 8259A) ;|per settare il bit corrispondente a COM1, nel IN AL,_8259mk ;|suo Registro di Abilitazione Interruzioni HW, MOV CS:[Dep8259],AL;|[0021H]. La linea IRQ4 (in arrivo da COM1) Š AND AL,11101111B ;|abilitata forzando a 0 il bit4; la tecnica OUT _8259mk,AL ;|utilizzata non altera i valori degli altri bit ;|di questo Registro, lasciando abilitate altre ;|eventuali fonti di interruzione (di solito ;|almeno il Timer di Sistema e la Tastiera). Una ;|copia dello stato originale di questo Registro ;|Š salvata nella variabile locale [Dep8259], in ;|attesa di ripristinarlo alla fine del programm ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[0021H]| 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | ECH ;| \-no*-no*-no*-si*-no*-no*-si*-si/ TIMER ;|LPT1 IRQ7-/ | | | | | | \---IRQ0 ;|DISK IRQ6-----/ | | | | \--IRQ1 KEYB ;|LPT2 IRQ5---------/ | | \------IRQ2 USER ;/COM1 IRQ4-------------/ \----------IRQ3 COM2 RET ;/---------------------------------------------------------------------------\ ;|PROCEDURA : OldInt0C | ;|DESCRIZIONE: Questa procedura ripristina le condizioni presenti nel sistema| ;| prima dell'esecuzione del nostro programma, chiamato a soddi-| ;| sfare le richieste d'interruzione generate dalla porta seriale| ;| (UART) COM1; recupera il valore del vettore INT 0CH originale| ;| e interviene sul Registro UART e su quello del controller| ;| delle interruzioni del computer (PIC 8259A) per impedire la| ;| possibilit… d'interruzione IRQ4 da parte della COM1. | ;\---------------------------------------------------------------------------/ OldInt0C: ;\Il ripristino di un Vettore Š operazione CLI ;|critica, per cui per tutto il tempo necessario ;/le interruzioni sono disabilitate ;\Per impedire all'UART di generare richieste HW ;|di interruzione Š necessario forzare a "0" la ;|sua linea OUT2 (pin31 UART); questa situazione ;|si ottiene portando a 0 il bit3 del Registro ;|di Controllo Modem [port_C],cosa che impedisce MOV DX,CS:[port_C];|il collegamento a livello hardware della linea IN AL,DX ;|INTR (pin30 dell'UART) alla linea IRQ4 del AND AL,00000011B ;|controller delle interruzioni, 8259A; in OUT DX,AL ;|condizioni normali le linee DTR (pin33 UART) e ;|RTS (pin32 UART) devono essere attive (cioŠ a ;|1) per cui anche i rispettivi bit0 e bit1 ;|saranno lasciati al loro valore originale ;|(presumibilmente a 1); il bit4 viene comunque ;|forzato a 0 (normale, no Lookback Mode) ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[port_C]| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 03H ;| \---*---*---*---*---*---*---*---/ ;|non usati-*---*---/ | | | | \DTR on ;|no LookBack Mode------/ | | \----RTS on ;/INT disabilitate ---OUT2--/ \OUT1-non usata ;\Si interviene sul controller delle interru- ;|zioni del computer (il PIC 8259A) per annulare ;|il bit corrispondente a COM1, nel suo Registro ;|di Abilitazione Interruzioni HW, [0021H]. La ;|linea IRQ4 (in arrivo da COM1) Š disabilitata MOV AL,CS:[Dep8259];|forzando a 1 il bit4; la tecnica utilizzata OR AL,00010000B ;|recupera lo stato originale di questo Registro OUT _8259mk,AL ;|prima dell'azione del nostro programma, recu- ;|perandolo dalla variabile locale [Dep8259], ;|mantenedo cosŤ inalterati i valori degli altri ;|bit e quindi le fonti di interruzione attive ;|in origine (di solito almeno il Timer di ;|Sistema e la Tastiera) ;| /-7-*-6-*-5-*-4-*-3-*-2-*-1-*-0-\ ;|[0021H]| 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | FCH ;| \-no*-no*-no*-no*-no*-no*-si*-si/ TIMER ;|LPT1 IRQ7-/ | | | | | | \---IRQ0 ;|DISK IRQ6-----/ | | | | \--IRQ1 KEYB ;|LPT2 IRQ5---------/ | | \------IRQ2 USER ;/COM1 IRQ4-------------/ \----------IRQ3 COM2 PUSH ES ;\ XOR AX,AX ;| MOV ES,AX ;| MOV DI,0030H ;|Punta con ES:DI la locazione 0000:0030H, LEA SI,Old_Int0C ;|contenente il nostro vettore CS:ServInt0C per MOV AX,CS:[SI] ;|il servizio INT 0CH dell'interuzione IRQ4 da MOV ES:[DI],AX ;|COM1 o COM3, e con CS:SI la variabile locale ADD DI,2 ;|[Old_Int0C], nella quale Š riposto il valore ADD SI,2 ;|del vettore originale, per ripristinarlo MOV AX,CS:[SI] ;| MOV ES:[DI],AX ;| POP ES ;/ RET ;***************************************************************************** ; ---------------------------------------------- B3_3Mou1 proc NEAR ; AREA DEDICATA AL MAIN PROGRAM ; ---------------------------------------------- ;----------------------------------------------------------------------------- ;/---------------------------------[Inizializza il PROTOCOLLO per il Test]---\ MOV Byte Ptr CS:[depPOR],COM_num;\Per cambiare PORTA utilizzata, Velocit… | MOV Word Ptr CS:[DepVEL],Baude ;|di ricetrasmissione e Protocollo Seriale | MOV Byte Ptr CS:[DepTIP],Protoc ;/cambia le costanti all'inizio del codice | ;\---------------------------------------------------------------------------/ ;\Inizializza i Registri della porta seriale in ;|accordo con i parametri di protocollo deside- CALL INIserial ;|rati (velocit… di linea, numero bit di dato ;|e di stop, tipo di parit…) e in funzione della ;|porta COMx desiderata (default COM1) ;|NB: lascia in uscita SI=0000H se la porta ;/ desiderata NON Š presente nel sistema ;\Predispone il Piano di Lavoro e inizializza le ;|Variabili necessarie per il Programma Seriale CALL DeskTop ;|NB: se il valore ricevuto in ingresso in SI Š ;|0 la porta seriale desiderata NON Š presente ;|nel sistema e la procedura impone automatica- ;/mente il rientro al DOS (a livello _OUT) ;\Rende disponibile una procedura di servizio ;|per le richieste d'interruzione generate dalla ;|porta seriale (UART) COM1, rimappando il ;|vettore INT 0CH per puntarla; salva il vettore CALL SetInt0C ;|originale per poterlo ripristinare in uscita e ;|interviene sia sui registri dell'UART che su ;|quelli del controller delle interruzioni del ;/computer (il PIC 8259A) ;--------------------------------------------------------------------- MOV Word Ptr CS:[Numero],00; Numero di Bytes ricevuti MOV Byte Ptr CS:[RigCorr],01;\Predispone la riga e la colonna di stampa cor- MOV Byte Ptr CS:[ColCorr],03;|rente al valore 2,3 (la riga viene incrementa- ;/ta automaticamente da GoToxy) MOV AL,1FH ;\Fissa il Colore da usare nella stampa dei dati MOV CS:[Colore],AL;| M_COLOR AL ;/ ;\Provvede a fissare la posizione iniziale del CALL GoToXY ;|cursore video (riga 1, colonna 0 ) e stampa ;/subito uno spazio a livello BIOS ;--------------------------------------------------------------------- ;\Se disponibile assume un byte dal Buffer ;|Circolare di Ricezione, lasciandolo in uscita xxx00: CALL RxD_Int ;|in AL, con AH=00H; se nel Buffer non ci sono CMP AH,00 ;|valori utilizzabili la procedura termina con JNZ xxx01 ;|AH=01H, per sottolineare che il dato in AL non ;|Š attendibile; in questo modo anche l'ese- ;|cuzione del programma pu• essere interrotta ;/con la pressione di un tasto qualunque CALL Stampa ;Se il dato Ricevuto Š buono lo si mette a video xxx01: MOV AH,01H ;\Altrimenti si controlla la pressione di Tasti INT 16H ;|SENZA FERMARSI se NON Š stato premut alcun JZ xxx00 ;|tasto (ffZ="1",Z) rimane comunque in attesa di ;/dati disponibili nel Buffer di Ricezione ;--------------------------------------------------------------------- CALL KEYwait ;\******* Gestione Menu interno ******** AND AL,11011111B ;| CMP AL,'Q' ;| con "Q" torna al DOS JNZ xxx00 ;/ ;--------------------------------------------------------------------- _OUT: PUSH AX ;\/--------------------------------------------\ M_COLOR 07H ;|| FASE STANDARD D'USCITA DAL PROGRAMMA | MOV DH,24 ;|\--------------------------------------------/ CALL BARRA ;| MOV DH,0 ;|Pulisce la prima e l'ultima riga del monitor CALL BARRA ;|(di solito assegnate al Titolo e al Menu) CALL RIP_cur ;|e fissa il cursore sull'ultima; con questo MOV DH,23 ;|artificio al termine del programma il "prompt" MOV DL,0 ;|cade nel punto ottimale, senza inquinare CALL SET_cur ;|l'immagine in uscita,ovviamente ancora a video POP AX ;/ ;\Ripristina le condizioni presenti nel sistema ;|prima dell'esecuzione del nostro programma di ;|gestione interruzioni dalla porta seriale COM1 ;|recupera il vettore INT 0CH originale e CALL OldInt0C ;|interviene sul Registro UART e su quello del ;|controller delle interruzioni del computer ;|(PIC 8259A) per impedire alla porta COM1 la ;/possibilit… d'interrompere ancora, via IRQ4 ;\Torna al DOS liberando la memoria usata dal ;|programma, restituendo il controllo al proces- ;|so padre (generalmente COMMAND.COM); il valore MOV AH,4CH ;|posto eventualmente in AL prima di uscire pu• INT 21H ;|essere testato a livello DOS con la funzione ;|4DH o mediante la lettura della variabile DOS ;/"ERRORLEVEL" B3_3Mou1 ENDP _prog ENDS END INIZIO