LA TASTIERA PS2

Tutorial per Scoprirne i segreti e come Connetterla ad un qualsiasi PIC…


 
 
 
 




 

INTRO

Ero perplesso se scrivere questo articolo in quanto pensavo a chi potesse interessare; ma facendo una ricerca ho trovato pochissimi articoli sull’argomento e l’unico che ne descriveva le funzioni non era molto esaustivo almeno per me.

Sono sempre stato molto curioso anche per deformazione professionale (sono stato progettista software per una grande multinazionale) e non sono soddisfatto fino a quando le cose che studio o che progetto non funzionano come voglio io pur rispondendo alle necessità di chi poi deve usare il software.

 




 
LA STORIA

Circa quattro anni fa dopo aver comprato la EASYPIC5 della MikroElectronica, cominciai a studiare il mondo dei PIC cercando di scoprire il loro funzionamento e le varie interfacce collegabili. Tra questi dispositivi e grazie alle librerie software in dotazione, c”era anche l’interfacciamento di una tastiera per PC. Ho provato il software ma ho dovuto poi accantonare il tutto per una serie di motivi: tempo, problemi, vari ma soprattutto insoddisfazione per il software in dotazione.

Ho ripreso in questo ultimo mese lo studio di questa tastiera ma con un preciso scopo: capirne il funzionamento e implementare un software indipendente dal tipo di PIC usato.

Ci sono in internet parecchi articoli (per il 90% in inglese e pochissimi in italiano) che descrivono la logica di esercizio di un tastiera PS2: li ho letti tutti (almeno i più interessanti e completi) ed alcuni anche con esempi tutti però scritti in assembler per altri sistemi o in “C”. E di difficile comprensione: Vi ricordo che un programma (scritto in qualsiasi linguaggio) è sempre frutto di un parto mentale con una logica strettamente personale.

 





 
L’HARDWARE

Una tastiera PS2, una piccola interfaccia, un qualsiasi PIC (ho usato il PIC16F887). L’interfaccia che ho preparato potrebbe essere inutile in quanto sulla EasyPic5 è già predisposto un connettore PS2 con le sue resistenze e connesso (DATA e CLOCK sui pin RC0 e RC1). Però a me serviva l’indipendenza dai pin.

a sinistra una tastiera normale standard a destra la piccola interfaccia per la connessione della stessa.

Una qualsiasi tastiera con connettore din a 5 o 6 pin (tipo PS2) si connette al sistema, che sia PC o PIC, attraverso due pin di alimentazione (5V/GND) e due pin di interfaccia denominati CLOCK e DATA. La figura seguente mostra il pinout delle connessioni:

I segnali CLOCK e DATA sono definiti a “collettore aperto” e necessitano di due resistenze di pull_up a +5V con valore da 4,7 a 10K. Nella mia schedina di interfaccia non sono visibili in quanto nascosti da uno switch interruttore dell’alimentazione, che ho inserito per resettare la tastiera. (Vedremo più avanti il perchè). Il connettore femmina è stato “prelevato” da una piastra per pc bruciata (sigh !).

Il segnale di CLOCK viene SEMPRE trasmesso dalla tastiera e la sua frequenza viaggia nel range dei 10,0 – 16,7 Khz. Quindi il CLOCK rimane alto dai 30 ai 50us. I dati vengpno trasmessi attraverso il segnale DATA controllando, prima, che il segnale di CLOCK sia a livello alto per almeno 50us. Questo in quanto è possibile portare da Host la linea di clock a livello BASSO per inibire la trasmissione dati dalla tastiera. Ciò può essere utile per dare tempo all’ HOST di elaborare il dato ricevuto. La trasmissione dei dati è basata su un protocollo sincrono a 11 bit nella seguente forma:

  • Un bit di start (sempre “0”)
  • 8 bit dati a partire dal meno significativo
  • 1 bit di parità (se = 1 il numero dei bit ALTO è pari, se = 0 è dispari)
  • 1 bit di stop (sempre “1”)

Come nel seguente diagramma:

La ricezione dei dati trasmessi dalla tastiera vengono rilevati dall’ HOST sul fronte di discesa del CLOCK: in sostanza quando il segnale DATA passa da livello “1” a livello “0” (start bit), l’ HOST può cominciare a catturare i bit che seguono compattando i successivi 8 BIT per ottenere il dato trasmesso che d’ora in poi chiamerò SCAN_CODE. L’ Host poi proseguirà la ricezione fino all’ undicesimo bit. Il bit di parità (che nella mia applicazione viene ignorato) potrà essere utilizzato per verificare che i dati trasmessi siano stati correttamente ricevuti.

Non dobbiamo però trascurare che il protocollo di trasmissione è BIDIREZIONALE: ovvero la tastiera oltre a trasmettere può anche ricevere byte di comando per la sua personalizzazione.

Se l’ HOST vuole trasmettere deve attenersi ad una sequenza particolare:

  • Inibire la trasmissione dalla tastiera mettendo a massa il segnale di clock per almeno 100us
  • Mettere a massa anche la linea dati e rilasciare il clock

Questa sequenza istruisce la tastiera a ricevere i dati e inizia a generare il CLOCK (come già detto questo segnale è sempre gneerato dalla tastiera). L’HOST inizia allora la trasmissione dei bit secondo il seguente diagramma:

Alla fine di questo frame l’Host si aspetta un ACK bit da parte della tastiera e rilascia la linea dati. Se questa non viene rilasciata la tastiera capisce che c’è stato un errore e continua a generare il clock finchè detta linea non viene rilasciata.

A tal proposito ho notato, nella letteratura specifica ripresa da internet, modi diversi di interpretazione di questa sequenza e non tutti sono chiarissimi.

La mia applicazione per adesso, si limita soltanto alla gestione dei dati trasmessi dalla tastiera: mi riservo in un immediato futuro di implementare anche la gestione dei comandi verso la tastiera (e non sono pochi: per esempio c’è un comando specifico per accendere e spegnere i LED: NUM CAPS SCROLL).

Pensavate forse che bastava premere NUM LOCK o CAPS LOCK per accendere i relativi LED ?? e che la tastiera reagisse a questi comandi ??….. ERAVATE IN ERRORE !!!!

 

IL SOFTWARE
Cominciamo con capire che cosa significa SCAN_CODE: il compito della tastiera è principalmente quello di scandire attraverso il suo hardware i segnali provenienti dalla pressione di uno o più tasti per generare il cosidetto SCAN_CODE.

Detto codice si riferisce NON AL VALORE IMPRESSO DALLA SERIGRAFIA DEL TASTO bensì dalla sua posizione nella matrice dei tasti stessi: e potete notare che anche per tastiere diverse con un minore o maggiore numero di tasti presenti, questo codice non supera mai il valore “7F”: in pratica 128 tasti diversi ma i codici trasmessi sono sempre gli stessi. Ma ci sono eccezioni alla regola !.

Quindi quando viene premuto un tasto la tastiera trasmette il suo SCAN_CODE e non il valore del tasto: Esempio: se io premo “a” non viene inviato ll suo corrispondente valore ascii “61h” bensì il valore “1Ch”. E questo vale per tutti i tasti della tastiera. E’ evidente la ragione di questo sistema: rendere indipendente il tasto da ciò che c’è impresso nella sua serigrafia. Basta verificare: in ITALIA c’è la cosidetta tastiera ITALIANA, ma in USA o Inghilterra vige la tastiera internazionale, in Germania alcune lettere sono particolari per il loro linguaggio; per non parlare poi di quella cinese o araba.

Ma questi SCAN_CODE non sono univoci: lo standard odierno definisce per default Scan_Code_Set di tipo 2 mentre è possibile avere anche Scan_Code_Set 1 e 3. Però soltanto dietro comando specifico da inviare alla tastiera.

Quando accendiamo la tastiera (ho usato un microswitch per accenderla e spegnerla in modo indipendente: vedi foto interfaccia), questa effettua il BAT (Basic Assurance Test) visibile dall’accensione simultanea dei 3 led ed invia all’ HOST il codice “AAh” se non ci sono problemi o “FCh” viceversa. Quindi assume per default atri parametri:

  • TypeMatic: iniziale di 500 ms
  • TypeMatic: velocità di ripetizione 10,9 hz
  • Scan_Code_set: 2
  • Make_Code, Break_Code e TypeMatic abilitati

Cosa sono ?: TypeMatic inziale è il tempo che intercorre tra un tasto e la RIPETIZIONE del tasto stesso: ogni tasto che segue viene trasmesso alla velocità di 10,9 hz. Fate una prova: premete un tasto qualsiasi e tenetelo premuto: il secondo carattere che appare dopo la pressione del primo apparirà dopo 1/2 secondo; a seguire tutti gli altri alla velocità già detta. Per fare la prova aprite il blocco note di Windows e cominciate a scrivere.

Entrano adesso in ballo altre due definizioni secondo lo standard: MAKE_CODE e BREAK_CODE.

Il Make_Code deriva dallo Scan_Code e i due termini possono essere facilmente confusi ma sostanzialmente indicano la stessa cosa. Il Make_Code è il codice che viene inviato dalla tastiera a seguito della pressione di un tasto. Una tabella di corrispondenza associa al Make_Code il valore ascii del tasto premuto. Cosa che deve fare l’ HOST.

Il BREAK_CODE è in codice composto di due Byte che la tastiera invia a seguito del RILASCIO del tasto premuto. Qui occorre fare una precisazione. Quando viene premuto un tasto la tastiera invia subito il Make_Code e se non viene rilasciato continua ad inviare lo stesso codice. Ma se il tasto viene rilasciato invia i due byte definiti dal BREAK_CODE.

Facciamo un esempio:

  • Viene premuto il tasto “a”: la tastiera invia “1Ch”
  • Viene rilasciato il tasto “a”: la tastiera invia due byte: “F0h” “1Ch”
  • Il tasto “a” viene tenuto premuto: la tastiera invia “1Ch” “1Ch” “1Ch” fino a quando non viene rilasciato quindi invia “F0h” “1Ch”.

Chiaro ?.

Sembrerebbe semplice a prima vista. In effetti lo è se ci limitiamo a queste affermazioni. La realtà è però leggermente diversa.

Come ho già specificato la tastiera invia il Make_Code (da adesso lo chiamerò così) per ogni tasto premuto qualunque esso sia. Quindi l’ Host riceverà i codici relativi anche ai tasti “ALT”, CTRL dx e sx”, “TAB”, “ESC”, “SHIFT dx e sx”, “ALT GR”, NUM LOCK”, CAPS_LOCK”, SCROLL_LOCK”, i tasti Freccia (UP, DN, Left, Right) il tastierino numerico con la doppia funzione e i tasti di funzione da F1 a F12. Senza contare che su alcune tastiere moderne ci sono alcuni tasti chiamati “Windows” la cui pressione permette di accedere direttamente ad alcune funzioni. (Esempio. il richamo del menù di sistema). Anche questi tasti hanno il loro Make_Code.

Anche questi tasti subiscono la regola del Make_Code + Break_Code.

E’ ovvio che il software residente sull’ Host deve poter prevedere tutte le combinazioni possibili ed agire di conseguenza. La mia applicazione consiste in due moduli: uno per la cattura di quanto inviato dalla tastiera ed uno per la gestione del tasto stesso. Un altro programma effettua la prova dei due moduli: riceve i make_code li analizza ed invia tramite RS232 il valore ascii del tasto premuto o i valori esadecimali dei tasti speciali. L’ Hyper_Terminal di windows (19200,n,8,1) funziona da visualizzatore.

Per comprendere meglio l’associazione tra Make_Code e relativi codici ascii ho preparato una tabella in Excel così definita:

Deve essere così interpretata: tutti i valori da “00h” a “7Fh” rappresentano i codici Make_Code che la tastiera invia a seguito della pressione di un tasto. Fa eccezione il tasto di funzione “F7” che ha codice “83h”. Tutti i valori da “89h” a “F1h” NON sono Make_Code ma sono i codici ASCII dei relativi tasti MAIUSCOLI e dei tasti numerici del tastierino numerico che io gestisco nel mio applicativo. Per trovare a quale Make_Code corrisponde un tasto basta cercare nella tabella il carattere corrispondente tenendo presente che alcuni tasti hanno un doppio significato. Esempio: “1” vale “16h” ma anche “!” vale “16h” quindi la differenza deve farla l’applicativo che deve verificare se è stato premuto “anche” il tasto “SHIFT”

Le caselle vuote non hanno nessuna corrispondenza. Da notare che questa tabella è relativa alla tastiera ITALIANA!. Ci tengo a questa precisazione perchè le librerie PS2 fornite dal MicroBasic contemplano solo la tastiera internazionale.

Ma ci sono sempre delle eccezioni: “l’eccezione conferma la regola” si dice. Nelle tabelle sottostanti le eccezioni che dicevo:

Come potete vedere le due tabelle dimostrano le eccezioni: i tasti particolari sono preceduti dal codice “E0h” seguito dal Make_Code del tasto premuto. Le cose si complicano se viene attivato il NUM_LOCK come da tabella a sinistra. Attenzione però che sia NUM_LOCK che CAPS_LOCK vengono visti come switch ON/OFF dall’applicativo che li gestisce.

Ne mancano ancora due:

  • PRINT SCREEN: “E0” “12” “E0” “7C” “E0” “F0” “7C” “E0” “F0” “12”: ben 10 codici che vengono inviati insieme.
  • PAUSE/BREAK: “E1” “14” “77” “E1” “F0” “14” “F0” “77” : ancora speciale perchè comincia con “E1” ma il mio applicativo lo ignora.

Tutte queste condizioni le ho identificate attraverso l’applicativo leggendo quanto arrivava dalla tastiera e visualizzandolo in esadecimale sempre tramite Rs232 e Hyper_Terminal. Ho così scoperto che non è proprio facile ed immediato analizzare quanto arriva dalla tastiera dato che le condizioni sono molteplici e varie. Vi faccio alcuni esempi: (Tutti i valori sono in esadecimale)

  • Semplice pressione di un tasto: 1C F0 1C: pressione del tasto “a” subito rilasciato
  • Ripetizione di un tasto: 16 16 16 16 16 16 F0 16: Ripetizione del tasto “1” sei volte e poi rilasciato.
  • Pressione dei tasti “SHIFT” e “a” : 12 1C F0 1C F0 12: tasto shift (12) tasto “a” (1C) rilasciato lo “shift” rilasciato il tasto “a”.
  • Pressione del tasto INS con Num_Lock spento: E0 70 E0 70 F0
  • Stesso tasto INS con Num_Lock attivo: E0 12 E0 70 E0 F0 70 E0 F0 12 (Notare che il codice “12” corrisponderebbe al tasto “Shift sinistro).

C’è da perdere la testa: le combinazioni sono molteplici ma con calma e pazienza sono riuscito comunque ad implementare un programma che mi permette di gestire completamente una qualsiasi tastiera.

 





 
MODULI APPLICATIVI

Vediamo adesso come ho sviluppato i due moduli applicativi scritti in MicroBasic Pro. Questi moduli sono alla versione 1 e possono essere suscettibili di modifiche e successive implementazioni per migliorie o risoluzione di bug.

Per prima cosa ho sviluppato il modulo “Soft_Ps2” attraverso la routine Capture_Bit. Il segnale di CLOCK e il segnale di DATA sono connessi al port A bit “0” e bit “1”. Il modulo esegue la scansione del segnale di clock fino a quando questi non diventa “basso”: cattura il bit presente nel segnale data e lo inserisce in un buffer. Poichè il primo bit è il segnale di start (bit “0”) la cattura prosegue fino al 9^ shiftando verso destra i bit già catturati in precedenza nel buffer. Ogni bit viene catturato solo quando il segnale di clock passa da “alto” a “basso”.

Non è stato necessario creare dei delay o utilizzare degli interrupt sulla transizione del segnale di clock da “alto” a “basso” ma semplicemente attraverso un loop: la bufferizzazione dei bit termina al 9^ bit (perdendo in questo modo il bit di start) mentre la scansione del clock termina all’ undicesimo bit. In questa versione non si controlla il bit di parità e si presume che la trasmissione sia esente da errori. Una implementazione futura potrebbe fare questa verifica ma occorre che venga anche implementata la routine di trasmissione da Host a Tastiera per rivelare l’errore.

Poichè i tempi di rilevazione dei bit e la loro cattura sono abbastanza ristretti, all’ inizio della routine viene posto in INPUT il bit di clock che per effetto del PULL_UP si presenta alla tastiera a “1” logico. All’ uscita della routine viene posto in OUTPUT questo bit e portato a “0” logico: questo inibisce la tastiera dall’ inviare altri byte; come già detto in precedenza, la tastiera prima di inviare controlla che la linea di clock sia “ALTA”. Questo accorgimento permette di verificare ogni byte inviato dalla tastiera indipendentemente dal tempo occorrente per la sua conversione ed utilizzo da parte dell’ applicativo.

Ho verificato questa soluzione analizzando il listato ASM del programma di test della PS2 in dotazione tra gli esempi del MicroBasic in quanto non ero molto convinto pensando di dover adottare un circuito HW diverso.

Utilizzando questo modulo ed un piccolo programma di test ho potuto verificare cosa viene inviato dalla tastiera byte per byte per poter successivamente implementare il modulo di conversione. Ecco alcuni esempi:

5AF05A 33F033 2C2DF02CF02D 2CF02C 2CF02C 0CF00C0CF00C 2EF02E2EF02E 35F03535F035

Sono stati premuti vari tasti e rilasciati.

Il secondo modulo PS2_SCAN_KEY effettua l’analisi e la conversione dei Make_Code arrivati. La guida per la conversione è composta da due tabelle: la prima di 256 byte serve per effettuare la conversione in Ascii dei caratteri minuscoli, maiuscoli, numerici anche dal tastierino numerico. La seconda di 144 byte serve per decodificare i caratteri speciali: per intendersi quelli complessi come ALT+carattere o CTRL+ carattere e i tasti di funzione. Sia nella prima che nella seconda tabella i valori “00” sono la spia per verificare che il Make_code ricevuto deve essere trattato in altro modo oppure semplicemente ignorato.

Mi rendo conto che non è semplice spiegare la logica di funzionamento: il modulo da solo occupa circa 1K + le tabelle. Nelle tabelle sottostanti troverete la decodifica completa: la routine esce con due parametri: ASCII_VALUE e SPECIAL_VALUE ed assumono i valori specificati nelle sottostanti tabelle.

Altri tasti presenti su alcune moderne tastiere per accedere direttamente alle funzioni di Windows:

Per finire un esempio della schermata di prove con L’Hyper_Terminal.

Le scritte tra parentesi sono state inserite a mano per chiarezza.
 
CONCLUSIONI

Non voglio tediarVi ancora e spero di non aver scritto strafalcioni. Questo articolo vuole essere più che altro un tutorial su come funzionano le tastiere PS2. Nel link sottostante troverete i moduli scritti in MicroBasic Pro. Utilizzano un PIC16F887 con il software Usart integrato. Per la visualizzazione su PC usate l’ Hyper_Terminal di Windows (19200,n,8,1) o un qualunque altro software di comunicazione. Il programma di test vi permette di verificare tutto ciò che viene dalla tastiera (rispondere “y” alla richiesta) oppure di verificare cosa viene digitato on formato leggibile.

Potete scaricare il firmware scritto con MIKROBASIC al seguente LINK!!!

Grazie per l’attenzione e alla prossima….

Gvsoft (Febbraio 2013)





 

[Voti Totali: 0 Media Voti: 0]
Segui la Nostra Pagina Facebook: Facebook

2 pensieri su “LA TASTIERA PS2

  1. Complimenti ottimo tutorial
    Nel lontano 2008 trovai un progetto di un keyboard viewer dove con un Pic16F84A e un display LCD si poteva leggere sia l’HEX del tasto premuto che il suo ASCII
    Oggi c’è un progetto simile per tastiera USB? Che PIC dovrei usare per rifare il medesimo progetto non più con il protocollo PS/2 ma con USB?

    • Il protocollo USB è un protocollo seriale: se vai a vedere le connessioni (VCC,GND data+, data-) ma è abbastanza complicato rispetto ad una seriale standard.
      Ti suggerisco di documentarti su internet: c’è una vasta documentazione purtroppo quasi tutti in inglese.
      Ciao
      gvsoft

Rispondi a Tury Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *