Proviamo con la porta parallela
Generalmente il computer è dotato di una sola porta stampante a cui possono essere connesse la stampante ed altri dispositivi ad interfaccia parallela (ZIP, scanner, etc.). Essa è conosciuta anche come LPT, porta stampante, printer port, oppure ancora interfaccia Centronics. E' facilmente riconoscibile guardando il computer dall'esterno: si presenta come un connettore a 25 poli DB25 femmina.
Oggi spesso rimane inutilizzata in quanto molti dispositivi, tra cui le stesse stampanti, utilizzano la porta USB. La presenza di un bus I/O ad 8 bit la rende utilizzabile per interfacciare semplici circuiti elettronici. Per utilizzarla con maggiore comodità per la nostra prova ci serviremo di un cavo di prolunga parallelo maschio/maschio, come quello mostrato in fotografia, in modo da avere sul nostro tavolo i segnali provenienti dal retro del computer.
Collegheremo quindi il connettore A al computer ed il connettore B alla semplice interfaccia descritta di seguito e costituita essenzialmente da un connettore femmina, 8 led ed 8 resistenze da 1000 Ohm. Quest'ultimo connettore è mostrato dal lato delle saldature, infatti c'è una perfetta corrispondenza con la piedinatura del connettore B dove sarà inserito.
Il risultato che vogliamo ottenere è semplicemente l'accensione programmata dei vari LED. Pertanto il software, su macchine Intel compatibili, dovrà realizzare i seguenti punti:
L'esempio fa riferimento al dispositivo di indirizzo 378h, ma funziona ugualmente bene con il dispositivo di indirizzo 278, basta modificare nel listato il valore della costante LPTPORT.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; ioled_1.asm ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;compilare con nasm+gcc %macro @ioperm 3 mov ebx,%1 ;;Numero porto iniziale; mov ecx,%2 ;;Quantita' di porti in successione mov edx,%3 ;;Richiesta: 1=Abilitazione, 0=Revoca mov eax,101 ;;Funzione sys_call=ioperm int 80h or eax,eax ;;Test esito: "jns okay" %endmacro %define LPTPORT 378h ;Da modificare, se necessario global main ;necessario per il linker gcc extern usleep, printf section .data msgerr db "NON abilitato all'uso dei porti di I/O! " db "Occorrono i privilegi di ROOT.",0Ah db "Oppure si e' verificato un ERRORE nel caso " db "si sia in ROOT.",7,0Ah,0 durata dd 500000 section .text main: @ioperm LPTPORT,1,1 ;Richiesta Permesso LPTPORT jns okay jmp err okay: call seq01 ;Chiamate output LPTPORT call seq02 jmp exit ;:::::::::::::::::::::::::::::::;ON e OFF di ciascun LED da D0 a D7 seq01: mov ecx,8 ; mov al,1 ;Imposta D0 acceso (ON) mov dx,LPTPORT wrk01: out dx,al call delay shl al,1 ;Passa al LED successivo loop wrk01 ret ;:::::::::::::::::::::::::::::::;8 lampeggi di tutti i LED seq02: mov ecx,8 ; mov dx,LPTPORT wrk02: mov al,0FFh ;Imposta tutti accesi out dx,al call delay mov al,0 ;Imposta tutti spenti out dx,al call delay loop wrk02 ret ;:::::::::::::::::::::::::::::::;Routine di ritardo delay: push dword [durata] ;Imposta durata in microsecondi call usleep add esp,4 ret ;:::::::::::::::::::::::::::::::;Gestione Errori e Uscita err: push dword msgerr ;Passa il Ptr Stringa call printf add esp,4 ;Riallinea lo Stack exit: @ioperm LPTPORT,1,0 ;Revoca Permessi I/O ret ;EOF :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Nella tabella seguente c'è una descrizione sintetica dei singoli pin:
Parallela Normale | Parallela ECP | ||||
---|---|---|---|---|---|
Pin | Nome | Descrizione | Nome | Descrizione | Annotazioni |
1 | /STROBE | Strobe | nStrobe | Strobe | out - Validità dei dati disponibili da D0 a D7 |
2 | D0 | Data Bit 0 | data0 | Address, Data or RLE Data Bit 0 | out - Byte inviato alla stampante |
3 | D1 | Data Bit 1 | data1 | Address, Data or RLE Data Bit 1 | out - Byte inviato alla stampante |
4 | D2 | Data Bit 2 | data2 | Address, Data or RLE Data Bit 2 | out - Byte inviato alla stampante |
5 | D3 | Data Bit 3 | data3 | Address, Data or RLE Data Bit 3 | out - Byte inviato alla stampante |
6 | D4 | Data Bit 4 | data4 | Address, Data or RLE Data Bit 4 | out - Byte inviato alla stampante |
7 | D5 | Data Bit 5 | data5 | Address, Data or RLE Data Bit 5 | out - Byte inviato alla stampante |
8 | D6 | Data Bit 6 | data6 | Address, Data or RLE Data Bit 6 | out - Byte inviato alla stampante |
9 | D7 | Data Bit 7 | data7 | Address, Data or RLE Data Bit 7 | out - Byte inviato alla stampante |
10 | /ACK | Acknowledge | /nAck | Acknowledge | in - Disponibilità a ricevere il prossimo dato |
11 | BUSY | Busy | Busy | Busy | in - Stampante/Buffer impegnata/o |
12 | PE | Paper End | PError | Paper End | in - Stampante senza carta |
13 | SEL | Select | Select | Select | in - Stampante pronta |
14 | /AUTOFD | Autofeed | /nAutoFd | Autofeed | out - Avanzamento riga |
15 | /ERROR | Error | /nFault | Error | in - Errore rilevato dalla stampante |
16 | /INIT | Initialize | /nInit | Initialize | out - Inizializza la stampante |
17 | /SELIN | Select In | /nSelectIn | Select In | out - Invia una richiesta alla stampante |
18 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
19 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
20 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
21 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
22 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
23 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
24 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
25 | GND | Signal Ground | GND | Signal Ground | gnd - Massa |
Si tenga presente che la porta parallela è stata sviluppata, all'origine, per la gestione della stampante, pertanto alcuni segnali, presenti sul connettore esterno, risultano invertiti (negati) come stato logico. In sostanza ciò che viene trattato dal programmatore a livello di registri LPTBASE+? viene ulteriormente modificato, su alcune linee, da porte logiche invertenti. La figura seguente illustra meglio la situazione.
Possiamo notare che oltre la LPTPORT+0, che abbiamo usato come output nel nostro primo esempio, ci sono anche la LPTPORT+1, che dispone di 5 ingressi, e la LPTPORT+2 che dispone di altri 4 pin di output. Il programmatore agisce sui 3 registri interni (area in grigio), mentre sui piedini del connettore (numeri in rosso) arrivano dei segnali che transitano attraverso dei buffer che, in qualche caso, sono invertenti. Attenzione: se ne tenga conto nelle applicazioni.
Complementi 1
Proponiamo, di seguito, un altro piccolo esperimento che consente di verificare l'acquisizione dei 5 bit della LPTPORT+1. La pila da 4,5 V consente di avere lo stato logico alto (valore compreso tra 1,8 e 5,1 Volt), quando l'interruttore è posizionato su on (interruttore chiuso). La resistenza da 10.000 Ohm mantiene lo stato logico basso quando l'interruttore è posizionato su off (interruttore aperto).
Il telaio del software è lo stesso di quello visto in precedenza, pertanto ci soffermiamo soltanto sulla parte relativa all'uso della LPTPORT+1. Poichè il bit 7 risulta invertito dall'hardware occorrerà un piccolo intervento, dopo l'input, per reinvertirne lo stato.
;:::::::::::::::::::::::::::::::::::::::; Acquisizione dell'input (Lettura) mov dx,LPTPORT+1 ; in al,dx ;:::::::::::::::::::::::::::::::::::::::; Inversione del bit più significativo mov ah,al ; duplica l'input nel registro ah not ah ; inverte tutti i bit di ah and ah,80h ; maschera i bit da 6 a 0 di ah and al,7Fh ; maschera il bit 7 di al or al,ah ; ricostruisce il byte ;:::::::::::::::::::::::::::::::::::::::; Opzioni correttive ; and al,0F8h ; opzione 1 (decommentare se necessario) ; shr al,3 ; opzione 2 (decommentare se necessario)
Attenzione: lo stato degli ultimi 3 bit non deve essere preso in considerazione in quanto non riferibile a nessun input proveniente dal connettore; pertanto la penultima riga di codice (opzione 1) può eliminare questa ambiguità azzerando sistematicamente i 3 bit. Un'altra possibilità è offerta dalla opzione 2 che, facendo scorrere verso destra il byte di 3 posti, azzera i 3 bit più significativi ed obbliga ad una rinumerazione verso il basso dei segnali ricevuti; a seconda delle situazioni e delle preferenze personali si può optare per le varie soluzioni.
Complementi 2
L'ultimo esperimento consiste nell'uso di LPTPORT+2 per l'emissione di 4 bit, tenendo conto sia della presenza di 3 inverter, sia del fatto che non dobbiamo alterare lo stato dei 4 bit più significativi.
;:::::::::::::::::::::::::::::::::::::::; Emissione output (Scrittura) mov dx,LPTPORT+2 ; in al,dx ; Lettura dello stato preesistente mov ah,pattern ; Simulazione input del pattern and ah,0Fh ; Maschera i 4 bit più significativi or al,ah ; Inserzione dei 4 bit del pattern in al ;:::::::::::::::::::::::::::::::::::::::; Inversione dei 3 bit negati mov ah,al ; duplica l'output nel registro ah not ah ; inverte tutti i bit di ah and ah,0Bh ; maschera i bit 7,6,5,4,2 di ah and al,0F4h ; maschera i bit 3,1,0 di al or al,ah ; ricostruzione del byte ;:::::::::::::::::::::::::::::::::::::::; out dx,al ; E, finalmente, invio sul porto
L'amore è per l'anima di chi ama ciò che l'anima è per il corpo.
François de La Rochefoucauld