Gestione di una tastiera PS/2 con il PICmicro

Tastiera PS/2

In applicazioni in cui l’interfaccia utente è piuttosto elaborata, può essere utile utilizzare una tastiera standard PS/2 (le classiche tastiere per PC) anziché il classico keypad 4x4. Ecco dunque come gestire una tastiera PS/2 utilizzando un microcontrollore PIC.

Le tastiere PS/2 per PC sono oramai un prodotto consumer: si trovano a pochi euro ed hanno le forme più svariate ed i colori più strani tant’è che spesso sono veri e propri oggetti d’arredamento. A parte l’aspetto estetico, sfruttare una tastiera di questo tipo consente di risparmiare linee di I/O sul micro e, allo stesso tempo, di disporre di 101 tasti ai quali è possibile associare qualsiasi funzione. Per riuscire in questo intento  è dunque necessario conoscere il protocollo  PS/2 quindi  disporre delle routine  che siano in  grado  di  gestirlo. È  proprio questo l’intento  di questo articolo.

La connessione PS/2

Codici dei tasti

Nel suo normale funzionamento, una tastiera PS/2 invia all’host (generalmente un PC, in questo caso il micro) una sequenza di bit (scan codes) che informa l’host su quale tasto è stato premuto. Qualora il tasto venga mantenuto premuto a lungo, il relativo codice viene inviato più volte, mentre al rilascio viene inviato il codice 0xF0 seguito dal codice relativo al tasto rilasciato. A ciascun tasto è associato uno ed un solo scan code come mostrato in figura 1 e la tastiera non è in grado di gestire autonomamente i tasti Lock (NumLock, CapsLock e ScrollLock). Ad esempio alla pressione di  NumLock  la  tastiera invia  il  codice opportuno all’host il quale memorizza questa informazione e risponde con il codice che consente di accendere il LED NumLock.

Figura 1. La mappa degli scan code per una tastiera standard

Figura 1. La mappa degli scan code per una tastiera standard

Tra i vari tasti disponibili su una tastiera standard, ve ne sono alcuni noti come extended keys. Questi sono codificati con uno scan code composto da più byte come indicato nella figura 1. Ad esempio nel caso del tasto AltGr il codice associato è 0xE011 dove 0xE0 indica che si tratta di un extended key. In questo caso, al rilascio, verrà inviato  prima  0xE0 seguito dal codice di rilascio 0xF0 quindi l’identificativo del tasto (0x11 nel caso di AltGr).

Codici dei comandi

Tra le informazioni che una tastiera può scambiare con un host (sia esso un PC che un microcontrollore) vi sono, oltre ai dati relativi ai singoli tasti, anche una serie di comandi. Di seguito sono riportati quelli principali.

Comandi da host a tastiera:
0xED (Impostazione LED) – è il comando utilizzato per  la  gestione  dei  LED NumLock,  CapsLock e ScrollLock. Alla ricezione di questo comando la tastiera risponde con un ACK e si mette in attesa di un successivo byte che determina il nuovo stato dei LED con la seguente convenzione: bit2 CapsLock, bit1 NumLock, bit0 ScrollLock.

0xEE (Echo) – inviando questo comando alla tastiera, questa risponde con un ulteriore comando Echo.

0xF0 (Set Scan Code Set) – è possibile scegliere il set di scan code da utilizzare inviando alla tastiera il codice 0xF0 attendere l’ACK dalla tastiera, quindi inviare un byte (0x01, 0x02 o 0x03) per selezionare il set di codici da utilizzare. Inviando il byte 0x00 la tastiera risponde con un byte che identifica il set in uso.

0xF3 (Set Typematic Repeat Rate) – Inviando alla tastiera questo comando è possibile impostare il Typematic Repeat Rate ovvero il ritardo di ripetizione nell’invio  dello  scan code quando  un  tasto viene mantenuto premuto. Alla ricezione di 0xF3 la tastiera risponde con un ACK quindi  si aspetta un byte che specifica il valore del Typematic Repeat Rate.

0xF4 (Keyboard Enable) – Svuota il buffer della tastiera, abilita la scansione e restituisce un ACK.

0xF5 (Keyboard disable) – Resetta la tastiera, disabilita la scansione e ritorna un ACK.

0xFE (Resend) – Alla ricezione di questo comando la tastiera invia nuovamente l’ultimo  byte inviato.

0xFF (Reset) – Resetta la tastiera. Comandi da tastiera ad host:

0xFA (ACK) – notifica  la corretta  ricezione di un comando.

0xAA (Power On Self Test Passed) – notifica il corretto superamento del test automatico eseguito all’accensione.

0xEE (Echo) – è la risposta al comando echo inviato dall’host.

0xFE (Resend) – Alla ricezione di questo comando l’host invia nuovamente l’ultimo byte inviato.

0x00 o 0xFF (Error) – notifica  una condizione di errore (tipicamente la saturazione del buffer).

 

Connessione con l’host

La connessione tra una tastiera PS/2 e l’host avviene per mezzo di un connettore Mini DIN maschio a 6 poli riportato  in figura 2. Come mostra la stessa figura, dei 6 poli del connettore, solo quattro sono effettivamente utilizzati. I due fili di comunicazione (KBDclk  e KBDdata) sono linee bidirezionali  open-collector. Lo standard prevede che una tastiera non assorba una corrente superiore a 300mA e questo dato è importante nel dimensionamento delle linee di alimentazione nell’ipotesi di utilizzare la tastiera con un proprio hardware.

Figura 2. Il connettore PS/2 lato tastiera con i relativi segnali

Figura 2. Il connettore PS/2 lato tastiera con i relativi segnali

Il protocollo: da tastiera verso host

Come già detto,  la comunicazione tra tastiera ed host è bidirezionale e l’host ha la priorità sulla comunicazione e può quindi inviare comandi alla tastiera in qualsiasi momento. La tastiera può invece inviare dati all’host solo se i segnali KBDdata e KBDclock  sono entrambi  a livello  alto.  In  questo senso il  segnale KBDclock  può  essere considerato come un “Clear-To-Send”: se l’host mantiene questo segnale a livello basso, allora la tastiera riempie il proprio buffer con i dati che via via arrivano sul canale KBDdata. La trasmissione dati da tastiera verso l’host, avviene in modo seriale su una trama di 11 bit (figura 3). Il primo  bit  è lo Start-Bit seguito dagli 8 bit  dati (a partire da LSB), quindi il bit di parità e lo Stop-Bit. La trasmissione è sincronizzata dal clock (generato sempre dalla tastiera) che permette di leggere i singoli bit  in corrispondenza dei fronti  di discesa del KBDclock. La frequenza di clock è compresa tra 20 e 30 KHz.

Figura 3. Trama di comunicazione tra tastiera e host

Figura 3. Trama di comunicazione tra tastiera e host

Il protocollo: da host verso tastiera

La comunicazione tra host e tastiera ha inizio da parte dell’host portando a livello basso la linea dati. Al fine di prevenire la situazione anomala in cui la tastiera inizia la trasmissione dati contemporaneamente rispetto all’host, viene mantenuto il clock a livello basso per un tempo superiore a 60ms quindi mantenuta  a livello  basso la  linea dati  finché  il segnale di clock non viene rilasciato (figura 4).

Figura 4. Trama di comunicazione tra host e tastiera

Figura 4. Trama di comunicazione tra host e tastiera

Una volta inviati gli otto bit ed il bit di parità la linea dati viene portata a livello alto (Idle) per un ciclo di clock, quindi la tastiera risponde con un ACK mantenendo a livello basso la linea dati per il successivo ciclo di  clock. Se  dopo  la trasmissione del bit  di parità la linea dati non viene messa nello stato Idle la tastiera continuerà a generare il segnale di clock fino al verificarsi di tale condizione.

Interfaccia con PIC

Acquisizione dello scan code

Lo schema elettrico dell’interfaccia con un microcontrollore PIC è piuttosto  semplice ed è riportata in figura 5. Si noti che sono sufficienti due resistenze di pull-up sulle linee KBDdata e KBDclock.

Figura 5. Schema di connessione tra PIC e tastiera PS/2

Figura 5. Schema di connessione tra PIC e tastiera PS/2

Dal punto di vista del firmware, alla pressione di un tasto sulla tastiera, il PIC ne acquisirà il relativo scan code e lo convertirà nell’opportuno codice ASCII che verrà memorizzato in un registro interno per il successivo utilizzo. L’acquisizione dello scan code viene effettuata utilizzando l’interrupt scatenato dal fronte di discesa della linea KDBclock su RB0/INT. L’interrupt handler si occuperà di acquisire il codice dalla linea KBDdata. Con questa tecnica, dopo undici cicli di KBDclock (quindi  dopo  undici occorrenze di interrupt su RB0/INT) l’interrupt  handler avrà completato l’acquisizione del dato notificando l’avvenuta ricezione mediante un flag ready. La conversione dello scan code nella corrispondente codifica ASCII viene effettuata dal programma principale una volta settato il flag ready e mantenendo la tastiera non attiva (linea KBDclock a livello basso). L’uso dell’interrupt permette di non bloccare il micro durante l’acquisizione del dato. Nel listato 1 l’interrupt handler.

        ORG     0x04      ; collocazione dell’handler

ISR     ;*** Salvataggio del contesto ***
        bcf INTCON,GIE    ; disabilita le interruzioni
        movwf W_TEMP      ; salvataggio di W
        swapf STATUS,W    ; salvataggio di STATUS
        movwf STATUS_TEMP
        clrf STATUS       ; spostamento su bank 0
        movfw PCLATH      ; salvataggio di PCLATH
        movwf PCLATH_TEMP
        clrf PCLATH       ; spostamento su ‘page zero’
        bcf STATUS,IRP    ; bank 0
        movfw FSR         ; salvataggio di FSR
        movwf FSR_TEMP

;*** attesa dello start bit ***
       tstf KBDcnt
       bnz _KBDdat
       btfsc KBDdatapin    ; controllo dello start bit sulla linea KBDdata
       goto _KBDabort      ; esce se lo start bit non è valido
       goto _INCF
;*** Acquisizione dato da tastiera
_KBDdat movfw KBDcnt        ; caricamento del contatore
        sublw d'8'          ; w = d'8' - KBDcnt
        bnc _KBDpari        ; salta se negativo(carry = 0)
        btfss KBDdatapin    ; acquisizione dato
        bcf KBD,0x07        ; salvataggio del bit a 0 in KBD
        btfsc KBDdatapin
        bsf KBD,0x07        ; salvataggio del bit a 1 in KBD
        bz _INCF
        rrf KBD,F           ; scorrimento di KBD
        goto _INCF
;*** si ignora il bit di parità***
_KBDpari movfw KBDcnt       ; caricamento del contatore
        sublw d'9'          ; w = d'9' - KBDcnt
        bnc _KBDstp         ; salta se negativo(carry = 0)
        goto _INCF
;*** controllo del bit stop***
_KBDstp btfss KBDdatapin    ; controllo di validità del bit stop
        goto _KBDabort      ; bit stop non valido
        bsf KBDflag         ; impostazione del flag ready
;*** disabilitazione della tastiera per prevenire l’arrivo di altri
; dati prima del completamento della decodifica in ASCII
        bsf STATUS,RP0      ; spostamento su bank 1
        bcf STATUS,RP1
        bcf KBDclktris      ; imposta KBDclock come uscita
        bcf STATUS,RP0      ; spostamento su bank 0
        bcf STATUS,RP1
        bcf KBDclkpin       ; disabilita la tastiera (KBDclock = 0)
;*** disabilitazione delle interruzioni su RB0/INT
        bcf INTCON,INTE
        goto _KBDterm
_KBDabort clrf KBD          ; dato non valido
_KBDterm clrf KBDcnt        ; azzeramento del contatore
        goto _KBDend        ; fine dell’interrupt handler
_INCF incf KBDcnt,F         ; incremento del contatore
_ISR_RS232error
_KBDend bcf INTCON,INTF     ; azzeramento dell’interrupt flag RB0/INT
;*** Ripristino del contesto
ISRend movfw FSR_TEMP       ; ripristino di FSR
       movwf FSR
       movfw PCLATH_TEMP    ; ripristino di PCLATH
       movwf PCLATH
       swapf STATUS_TEMP,W  ; ripristino di W
       movwf STATUS         ; ripristino di STATUS
       swapf W_TEMP,F
       swapf W_TEMP,W
       RETFIE
Listato 1

Ovviamente per utilizzare la routine del listato 1 è necessario dichiarare le opportune variabili e definire le giuste costanti come indicato nel listato 2. In fase di inizializzazione è necessario configurare le linee KBDdata e KBDclock come ingressi, configurare RB0/INT in modo da scatenare interruzioni  sul fronte di discesa (azzerando il bit INTEDG del registro OPTION_REG) quindi abilitare le interruzioni (mettendo ad “1” il bit INTE del registro INTCON).

#defineKBDdatapin PORTA,0x04              ; KBDdata
      #defineKBDdatatris TRISA,0x04       ; direzione per KBDdata
      #defineKBDclkpin PORTB,0x00         ; KBDclock (IntB)
      #defineKBDclktris TRISB,0x00        ; direzione per KBDdata

org 0x0C

     FLAGreg                        ; contiene vari flag
     KBDcnt                         ; contatore
     KBD                            ; registro dati (scan code e ASCII)
     KBDcopy                        ; registro dati (backup)
     #defineRELflagFLAGreg,0x00     ; flag di rilascio (0xF0)
     #defineSHIflagFLAGreg,0x01     ; flag tasto SHIFT(0x12 / 0x59)
     #defineSPEflagFLAGreg,0x02     ; flag codice esteso (0xE0)
     #defineCAPflagFLAGreg,0x03     ; flag tasto CAPS LOCK (0x0D)
     #defineALTflagFLAGreg,0x04     ; flag tasto ALT(0x11)
     #defineCTRLflag FLAGreg,0x05   ; flag tasto CTRL (0x14)
     #defineKBDflagFLAGreg,0x06     ; flag ready

     ; registri per il salvataggio del contesto
     W_TEMP                   ; per il salvataggio di W
     STATUS_TEMP              ; per il salvataggio di STATUS
     PCLATH_TEMP              ; per il salvataggio di PCLATH
     FSR_TEMP ; per il salvataggio di FSR
Listato 2

Conversione in ASCII del dato acquisito

Alla completa ricezione di uno scan code da parte dell’interrupt handler, il registro KBD conterrà  il codice acquisito dalla tastiera. A questo punto è necessario interpretarlo e convertirlo nella rispettiva codifica ASCII. La routine di decodifica (KBDdecode) può essere suddivisa in tre parti: la prima sezione imposta i flag in base al dato ricevuto dalla tastiera, la seconda individua un range in cui è compreso il dato ricevuto mentre la terza sezione opera la decodifica vera e propria restituendo nel registro KBD il risultato della conversione. Eccole analizzate nel dettaglio.  Il listato 3 riporta la prima sezione della routine KBDdecode che si occupa di attendere il rilascio di un tasto quindi di impostare correttamente i flag in base al dato ricevuto.

KBDdecode
       ;Sezione di impostazione flag

       ;Controllo rilasciamento tasto (scan code: F0)
       movfw KBD             ; Prelevamento dello scan code ricevuto
       movwf KBDcopy         ; Copia dello scan code
       sublw 0xF0            ; è stato ricevuto F0?
       bnz _KBD_1            ; no, salta a _KBD_1
       bsf RELflag           ; si, aggiorna il flag RELflag
       bcf SPEflag           ; Resetta sempre il flag codici estesi al rilascio
       goto _ClrStall        ; esci
_KBD_1 btfss RELflag         ; controlla il RELflag, è 0?
      goto _KBD_2            ; si, salta a _KBD_2
      bcf RELflag            ; no, azzera RELflag (rilasciamento tasto in corso)
      movfw KBD              ; premuto SHIFT(0x12)?
      sublw 0x12
      bz _clrSHI             ; si, salta a _clrSHI
      movfw KBD              ; premuto SHIFT DESTRO(0x59)?
      sublw 0x59
      skpnz                  ; no, salta
_clrSHIbcf SHIflag           ; azzera flag shift
      movfw KBD              ; premuto CAPS LOCK (0x58)?
      sublw 0x58
      bnz _clrALT            ; no, salta a _clrALT
      btfss CAPflag          ; il flag CAPflag è già settato?
      goto _setCAP           ; no, salta a _setCAP
      bcf CAPflag            ; si, azzera il flag
      goto _ClrStall         ; esci
_setCAPbsf CAPflag           ; setta il CAPflag
      goto _ClrStall         ; esci
_clrALTmovfw KBD             ; premuto ALT (0x11)?:
      sublw 0x11
      bnz _clrCTRL           ; no, salta a _clrCTRL
      bcf ALTflag            ; si, azzera il flag
      goto _ALTdec           ; salta alla decodifica di ALT
_clrCTRL movfw KBD           ; premuto CTRL (0x14)?
      sublw 0x14
      bnz _ClrStall          ; no, esci
      bcf CTRLflag           ; si, azzera il flag
      goto _CTRLhex          ; salta alla decodifica di CTRL
Listato 3

Il listato 4 riporta invece la sezione di codice relativa all’individuazione  del  range in  cui  collocare il dato ricevuto. Questa fase permette  di  accelerare notevolmente il processo di decodifica in quanto gli scan code (apparentemente  assegnati con  logica random ai vari tasti) sono in qualche modo  legati alla codifica  ASCII del relativo  carattere.

_KBD_2 ;verifica se è stato preventivamente ricevuto un codice speciale(0xE0)
       btfss SPEflag
       goto _KBD_3
       movfw KBD
       sublw 0x4A       ; ricevuto lo scancode 4A?
       bnz _NOSUP       ; no, salta a _NOSUP
       movlw '/'        ; si, memorizza '/' in KBD
       movwf KBD
       goto _ClrStall
_NOSUP ;verifica se lo scan code è minore o uguale a 0x5A
       movfw KBD
       sublw 0x5A       ; 0x5A - W
       bc _KBD_3        ; se risultato è maggiore di 0, salta a _KDB_3
       ;il valore è maggiore di 0x5A quindi è uno dei seguenti tasti:
       ;tasti freccia, 'Home', 'Del', 'PageUp', 'PageDown', 'Insert', 'End'
       ;Questa routine non prevede la gestione di tali tasti
       goto _ClrStall   ;esci
_KBD_3 ;verifica se lo scan code è minore o uguale a 0x61
       movfw KBD
       sublw 0x61      ; 0x61 - w
       bc KBD_dec      ; se risultato è maggiore di 0, salta alla tabella
       movlw d'14'
       subwf KBD,F     ; KBD = KBD - d'14'
       movfw KBD
       sublw 0x61     ; 0x61 - w
       bnc _KBD_4     ; re risultato minore di zero, salta a _KBD_4
       movlw d'25'
       addwf KBD,F    ; KBD = KBD + d'25'
       goto KBD_dec
_KBD_4 ;verifica se lo scan code è maggiore o uguale a 0x78 (0x86 - d'14')
       movfw KBD
       sublw 0x77     ; 0x77 - w
       bc KBD_dec     ; Risultato maggiore uguale a zero, salta
       ;Verifica dei codici estesi(0xE0): 0xD2 = 0xE0 - d'14'
       movfw KBD
       sublw 0xD2     ; 0xD2 - w
       skpnz
       bsf SPEflag    ; ricevuto codice esteso, imposta flag
       goto _ClrStall ; esci
Listato 4

Questa sezione di routine fa riferimento alla tabella di decodifica  KBDtable che contiene le corrispondenze tra scan code e codice ASCII. Tale tabella (riportata nel riquadro di approfondimento) è relativa ad una tastiera americana (figura 1) e può essere adattata a qualunque altro tipo di tastiera. Il listato 5 riporta infine l’ultima sezione della routine che è dedicata alla decodifica vera e propria. In questa sezione viene caricata la tabella di conversione, viene fatta la conversione minuscolo/maiuscolo (qualora sia necessaria) e vengono gestiti i tasti premuti contemporaneamente al tasto SHIFT (per la tabella di conversione dei tasti premuti con lo SHIFT si faccia riferimento al secondo riquadro di approfondimento).

;***SEZIONE DI DECODIFICA
KBD_decmovlw HIGH KBDtable
       movwf PCLATH
       movfw KBD
       call KBDtable        ; Acquisizione della corrispondenza nella tabella
       movwf KBD            ; salvataggio del risultato in KBD
       tstf KBD             ; controllo se acquisito valore nullo
       bz _ClrStall         ; valore nullo
       ;***Controllo su ALT ***
       ;btfsc ALTflag       ; controllo del flag
       ;goto _ALTstr        ; salta se flag è on
       ;***controllo su CTRL ***
       ;btfsc CTRLflag      ; controllo del flag
       ;goto _CTRLstr       ; salta se il flag è on
       ;***conversione dei caratteri in caratteri maiuscolo ***
       movfw KBD            ; controllo del range (le lettere sono tra 0x60 e 0x7A)
       sublw 0x60
       bc _SHICHR
       movfw KBD
       sublw 0x7A
       bnc _SHICHR          ; fuori dal range (il tasto premuto non è una lettera), salta
       movfw KBD
       btfsc CAPflag        ; controllo del flag caps lock
       goto _SHIset         ; flag on
       btfss SHIflag        ; controllo del flag shift
       goto _ClrStall       ; nessun flag
       goto _cnvCAP         ; flag CAPS lock, conversione in maiuscolo
_SHIsetbtfsc SHIflag        ; gestione del flag shift
       goto _ClrStall
_cnvCAPaddlw d'224'         ; conversione in maiuscolo (+ d'224')
       movwf KBD
       goto _ClrStall

_ClrStall
       BANK1
       bsf KBDclktris       ; imposta la linea clock come ingresso
       BANK0                ;
       bcf KBDflag          ; azzeramento dei flag
       bsf INTCON,INTE      ; abilitazione interrupt su RB0/INT
       RETURN

_SHIFT bsf SHIflag          ; gestione del flag shift
       RETLW 0              ; azzeramento di w (dato non valido)

_ALT bsf ALTflag            ; Gestione flag ALT
       RETLW 0              ; azzeramento di w (dato non valido)

_CTRL bsf CTRLflag          ; gestione del flag CTRL
       RETLW 0              ; azzeramento di w (dato non valido)

_CTRLstr ;non implementato
_ALTstr  ;non implementato
_ALTdec  ;non implementato

_CTRLhex ;implementato
       goto _ClrStall

;*** Gestione della decodifica con tasto SHIFT

_SHICHR
      btfss SHIflag
      goto _ClrStall
      ; controllo per tasti 'backspace', 'tab', 'linefeed' e 'enter' :
      movfw KBD
      sublw d'13'            ; d'13' - w
      bc _ClrStall

      movfw KBDcopy
      sublw 0x61             ; 0x61 - w
      bnc _ClrStall
      movfw KBDcopy
      sublw 0x3C             ; 0x3C - w
      bc _SHICH1
      movlw d'61'
      subwf KBDcopy,F        ; KBDcopy = KBDcopy - d'61'
      goto _SHICH3
      ;*** KBDcopy > 0x24 ?***
_SHICH1movfw KBDcopy
      sublw 0x24             ; 0x24 - w
      bc _SHICH2
      movlw d'35'
      subwf KBDcopy,F        ; KBDcopy = KBDcopy - d'35'
      goto _SHICH3
_SHICH2movlw d'4'
      addwf KBDcopy,F        ; KBDcopy = KBDcopy + d'4'
_SHICH3movlw HIGH KBDSHIFTtable ; preparazione al caricamento della tabella
      movwf PCLATH
      movfw KBDcopy
      call KBDSHIFTtable      ; Acquisizione del codice di conversione
      movwf KBD               ; posizionamento del risultato in KBD
      goto _ClrStall
Listato 5

PS/2 in MikroBASIC

Per completezza, ecco come viene gestita la connessione PS/2 utilizzando un linguaggio di alto livello come il Basic. Come riferimento sarà utilizzato il compilatore MikroBASIC di Mikroelekttronika. MikroBASIC prevede che la tastiera sia collegata al PIC mediante le consuete linee di clock e dati su cui devono essere collegate due resistenze di pull-up. Il micro deve lavorare con un clock di almeno 6MHz e il flusso dati non viene gestito mediante interruzioni. La comunicazione con la tastiera è, in questo caso unidirezionale, quindi  il PIC potrà  ricevere i dati dalla tastiera, ma non potrà inviarli (ad esempio per accendere i LED di CapsLock o NumLock). Le routine  messe a  disposizione da  MikroBASIC sono 2: Ps2_Init e Ps2_Key_Read.

Ps2_Init (dim byref port as byte, dim clock, data as byte)

La Ps2_Init inizializza il micro per la comunicazione con la tastiera e richiede tre argomenti ciascuno di un byte: il primo (port) è la porta su cui è connessa la tastiera; il  secondo (clock) è il  bit  della porta usato per la linea KBDclock; il terzo (data) è il bit della porta usato per la linea KBDdata. È evidente che clock e data dovranno essere diversi tra loro e compresi tra 0 e 7. Per usare la tastiera sulla PORTB usando RB2 come clock e RB3 come data, sarà sufficiente chiamare la funzione PS2_Init come: Ps2_Init(PORTB, 2, 3).

Tabella di corrispondenzascan code – ASCII

           ORG 0x??        ; impostare qui l’indirizzo a cui caricare la tabella
KBDtable                   ; valida per i tasti premuti senza SHIFT
         addwf PCL,F
         retlw 0           ; codice non valido
         retlw A'9'        ; F9 -> 9       0x01
         retlw 0
         retlw A'5'        ; F5 -> 5
         retlw A'3'        ; F3 -> 3
         retlw A'1'        ; F1 -> 1
         retlw A'2'        ; F2 -> 2
         retlw A'2'        ; F12 -> 2
         retlw 0
         retlw A'0'        ; F10 -> 0
         retlw A'8'        ; F8 -> 8       0x0A
         retlw A'6'        ; F6 -> 6
         retlw A'4'        ; F4 -> 4
         retlw 0x09        ; TAB
         retlw A'~'
         retlw 0
         retlw 0           ;                0x10
         goto _ALT         ; ALT (modifica solo il flag ALT)
         goto _SHIFT       ; SHIFT(modifica solo il flag SHIFT)
         retlw 0
         goto _CTRL        ; CTRL (modifica solo il flag CTRL)
         DT "q1"
         retlw 0
         retlw 0
         retlw 0           ;                0x19
         DT "zsaw2"
         retlw 0
         retlw 0                            0x20
         DT "cxde43"
         retlw 0
         retlw 0
         retlw A' '        ; SPAZIO
         DT "vftr5"
         retlw 0
         retlw 0            ;               0x30
         DT "nbhgy6"
         retlw 0
         retlw 0
         retlw 0
         DT "mju78"
         retlw 0
         retlw 0             ;              0x40
         DT ",kio09"
         retlw 0
         retlw 0
         DT ".?l;p"
         retlw A'-'
         retlw 0
         retlw 0              ;              0x50
         retlw 0
         DT "'"
         retlw 0
         retlw A'['
         retlw A'+'
         retlw 0
         retlw 0
         retlw 0                ; CAPS LOCK, (modifica solo il flag CAPflag al rilascio)
         goto _SHIFT            ; SHIFT
         goto _CRLF             ; CR,LF       0x5A
         retlw A']'
         retlw 0
         retlw A'|'
         retlw 0
         retlw 0
         retlw 0
         retlw A'<'              ;            0x61
         DT "0.2568"
         retlw 0                 ; ESCAPE     0x76
         retlw 0                 ; NUM LOCK
         DT "1+3-*9"
         retlw 0                 ; SCROLL LOCK 0x7E
         retlw 0x08              ; BACKSPACE
         retlw 0                 ;
         retlw 0                 ;
         retlw A'1'              ;             0x82
         retlw A'7'              ;
         retlw A'4'
KBDtableEND retlw A'7'
Struttura della KBDtable per i tasti premuti senza SHIFT

Ps2_Key_Read (dim byref value, special, pressed as byte) as byte

Questa è la funzione che ritorna informazioni  sul tasto che è stato premuto sulla tastiera. L’uscita di tale funzione darà il valore 1 se la lettura del dato dalla tastiera è avvenuta regolarmente, oppure 0 se il dato non è stato letto correttamente. Nel primo caso la variabile value conterrà direttamente il codice ASCII relativo al tasto premuto (per i tasti relativi ai caratteri, numeri, segni di punteggiatura e spazio) tenendo conto dell’inserimento o meno del CAPS Lock; special è invece un flag che notifica  la pressione dei tasti speciali (F1, F2, …, Enter, Esc, ecc…); infine pressed vale 1 se il tasto è premuto oppure 0 se rilasciato. Tale funzione deve essere chiamata necessariamente dopo la Ps2_Init. Un esempio di uso di tale funzione può essere quello del listato 7 in cui il programma entra in un loop infinito leggendo i caratteri dalla tastiera ed esce dal ciclo solo se viene premuto il tasto Enter (codice ASCII 13). Si noti che la condizione di uscita prevede un controllo sia sul codice ASCII (13, appunto) che sul flag spec relativo ai tasti speciali.

Ps2_Init (PORTB,2,3)
do
 if Ps2_Key_Read(val, spec, press) =1 then
      if (val=13) and (spec=1) then
           break
      end if
 end if
loop until FALSE
Listato 7

Tastiere wireless

Una volta noto il protocollo di trasmissione, "tagliare i fili" diviene abbastanza semplice. La comunicazione è composta da una serie di  bit  consecutivi quindi utilizzando un semplicissimo modulo  ibrido in radiofrequenza è possibile remotizzare l'intera tastiera rendendola wireless. La scelta è vasta data l'offerta del mercato: moduli ibridi in AM o FM alle frequenze di 433MHz o 868MHz. Viste le esigue distanze in gioco, non è da escludere anche una comunicazione ad infrarossi anche se questa tecnologia richiede che trasmettitore e ricevitore siano visibili reciprocamente. Nella figura 6 alcune possibili soluzioni per la remotizzazione della tastiera.

Figura 6. Alcune possibili soluzioni per la remotizzazione della connessione

Figura 6. Alcune possibili soluzioni per la remotizzazione della connessione

Tabella di corrispondenza scan code – ASCII (con tasto SHIFT)
KBDSHIFTtable
       addwf PCL,F
       DT "&*$#<"    ; 0x3D - 0x41
       retlw 0       ; dato non valido
       retlw 0
       retlw 0
       DT ")("       ; 0x45 - 0x46
       retlw 0
       DT "%>/"      ; 0x48 - 0x4A
       retlw 0
       retlw A':'    ; "\" 0x4C
       retlw 0
       DT "_`^"      ; 0x4E - 0x50
       retlw 0
       retlw A'"'    ; 0x52
       retlw 0
       DT "{="       ; 0x54 - 0x55
       retlw 0
       retlw A'!'    ; 0x57
       retlw 0
       retlw 0
       retlw 0
       retlw A'}'    ; 0x5B
       retlw 0
       retlw 0x5C    ; 0x5D
       retlw 0
       retlw A'@'    ; 0x5F
       retlw 0
KBDSHIFTtableEND retlw       A'>' ; 0x61
Struttura della KBDSHIFTtable per i tasti premuti con SHIFT

Leggi anche:

Sniffare i pulsanti premuti di una tastiera

Tabellone Elettronico

Scarica subito una copia gratis

2 Commenti

  1. Emanuele Bonanni Emanuele 23 Novembre 2015
  2. Maurizio Di Paolo Emilio Maurizio 2 Dicembre 2015

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend