|
La connessione tra l'host e la CPU 8052 è effettuata tramite una linea
seriale. Dato che la connessione è realizzata tramite un cavo di lunghezza
limitata, non si prevedono errori, salvo in caso di guasto hardware.
D'altro canto, una perdita di dati dovuta a ritardi nella risposta del software
và messa in conto.
Dobbiamo fare in modo che ogni comando riceva una risposta per garantire la
sua corretta ricezione, in caso contrario il mittente dovrà inviare di nuovo
il comando fintantochè non riceverà una risposta, fino ad un massimo di
cinque ritentativi, dopo di che assumerà che il comando sia stato perso.
Definizioni
Comando: è un messaggio che richiede al ricevitore dall'altro capo di
svolgere una determinata azione. Può essere una richiesta di informazioni (ad
esempio, 'Stato attuale dei pulsanti') o semplicemente la richiesta di un'azione (ad
esempio 'scrivi caratteri sul display'). Nel primo caso all'altra parte è richiesto
di inviare una risposta che contiene i dati voluti, mentre nel secondo caso l'altra
parte deve semplicemente eseguire un'azione.
Risposta: è un messaggio che trasporta i dati richiesti da un precedente
comando. Una risposta non richiede conferma, in quanto se viene persa o ricevuta male,
il comando che l'ha provocata verrà rispedito.
Conferma: è un particolare messaggio di risposta che indica che
un comando è stato correttamente ricevuto. Verrà inviato in risposta a tutti
quei comandi che non richiedono dei dati risposta.
Framing
Dato che esiste una possibilità di perdita di dati, non possiamo fare affidamento
sul fatto che un comando sia corretto e che i dati ricevuti siano completi. Se perdiamo il
byte del comando, il primo byte del dato verrà interpretato come comando, creando
la possibilità che venga eseguito per sbaglio.
Dobbiamo prendere in considerazione la possibilità di incapsulare tutti i messaggi
(comandi o risposte/conferme) in trame.
Per la struttura della trama ci possiamo ispirare al PPP in HDLC-like Framing
(PPP - Point to Point Protocol - in trame simili all' HDLC - High level Data Link Control)
come descritto nella RFC 1662. Dato che la linea è considerata sicura, si adotta
uno schema di controllo semplificato, come segue
FLAG: ogni trama è delimitata da due caratteri di flag
(uno di apertura ed uno di chiusura). Il valore del carattere di flag è
7E HEX. Il valore esadecimale 7E non può comparire tra i dati,
altrimenti la trama corrente verrebbe chiusa erroneamente. Se si deve trasmettere
un dato il cui valore sia 7E HEX, questo dato viene mascherato, facendolo precedere
dal carattere esadecimale 7D e viene trasformato in 5E HEX (7E XOR 20) per
evitare che la perdita accidentale del 7D causi una chiusura accidentale della
trame. Se si deve a questo punto trasmettere un dato il cui valore sia 7D, si
applica lo stesso mecanismo, trasmettendo 7D 5D (7D XOR 20). In questa maniera
le uniche sequenze 7E che saranno trasmesse sulla linea saranno sequenze di FLAG.
Ogni trama dovrà essere incapsulata in mezzo alla sua coppia
di flag.
DATI: è il pacchetto di dati da trasmettere. Si può trasmettere
un massimo di 253 caratteri. Il primo byte in ogni pacchetto è un byte di
comando.
CHEKSUM: è l'inverso della somma di tutti i byte del pacchetto (esclusi
i flag) troncata ad 1 byte. Il checksum va calcolato prima di applicare le regole di
trasparenza sopra spiegate
La lunghezza massima del pacchetto (valida solo per i pacchetti inviati dall'host alla
scheda) è stata calcolata considerando che il display contiene 250 colonne e che un
comando che invii una sequenza grafica completa dovrà essere lungo 250 colonne,
più le coordinate ed il comando stesso.
Dobbiamo tener conto che ci serviranno due buffer in ogni direzione (uno per un comando
ed un'altro per una risposta).
Regole del Protocollo
- Ogni carattere ricevuto al di fuori di una trama và scartato. Non sono
ammesse trame back to back, vale a dire che condividono il flag.
- La sequenza FLAG FLAG (7Eh 7Eh) deve venir considerata un singolo flag (è
il possibile risultato della perdita di un flag di apertura: il flag di chiusura
è il primo dei due flag, il secondo è il flag di apertura della trama
corrente, il contenuto della trama precedente è stato scartato in base alla
regola 1).
- Ogni trama con un checksum sbagliato và scartata
- Ogni comando/risposta/conferma è codificato in un singolo byte
- Ogni comando che non prevede una risposta deve prevedere una conferma
- Una risposta è una trama contenete i dati richiesti da un comando.
Il codice della risposta corrisponde al codice del comando cui risponde, con
il bit più significativo settato.
- Una trama di risposta ha il seguente formato:
Flag
|
Risposta
|
Dati della Risposta
|
Checksum
|
Flag
|
- Una conferma è una trama contenete un solo byte di dati, composto dal solo
codice (FFh = conferma). L'intera trama sarà dunque composta dalla seguente
sequenza esadecimale: 7E FF FF 7E, in forma grafica:
Flag
|
Conferma
|
Checksum
|
Flag
|
- Una risposta o una conferma possono essere distinti da un comando perché
il loro comando possiede il bit più significativo ad 1.
- Prima di aver ricevuto la risposta/conferma di un comando non è possibile inviare
altri comandi (ma ne può essere ricevuto uno)
- Un comando può essere inviato dall'host (il caso normale)
- Un comando può anche essere inviato dalla scheda (notifica di evento sulla
tastiera) (questo rende il protocollo simmetrico)
- I byte di una trama vanno inviati uno dopo l'altro, senza inserire pause
- Il ricevitore deve implementare un timeout per scartare una trama, nel caso
non arrivasse in tempo (utile nel caso venisse perso il flag 7E di chiusura)
- Anche la conferma/risposta deve essere inviata immediatamente alla ricezione
del flag di chiusura della trama del comando. Si potrà usare un timeout
più lungo per rilevare la mancanza di risposta
- Il timeout tra due caratteri ricevuti uno dopo l'altro deve essere maggiore di
4 tempi di carattere al boud rate corrente. Nel nostro caso sceglieremo
110 mS, equivalente a 2 timer ticks del PC (nel PC imposteremo 55mS, per garantire un
timeout compreso tra 55 e 110 mS, nell'8052, con clock a 11,0592 MHz, questro ritardo si
ottiene con un timet a 5mS - divisore 60298 - impostando il timeout a 22 'tick').
Un timeout così lungo ha un impatto limitato sulle prestazioni del protocollo.
Se non arrivano più caratteri, trascorso questo timeout la trame è
considerata terminata am non chiusa (non è stato ricevuto il flag di chiusura)
e quindi scartata. Questo meccanismo è implementato nella macchina a stati del
ricevitore di basso livello.
- Il timeout più lungo tra la fine della ricazione di un comando e la ricezione
della conferma/risposta è fissato in 495mS (da 440 a 495 mS per il PC -
99 tick per la scheda).
La macchina a stati della trasmissione si occuperà di gestire questo timeout.
La lunghezza massima di una trama è di 256 byte (253 dati + 2 flag + 1 checksum)
ma, considerando il fatto che questi dati possono venir mascherati, questa dimensione
può diventare 510. Un massimo teorico di 510 + 4 = 514 tempi di byte serve per
trasmettere una coppia comando/risposta (occorre ricordare che un conamdo con dei dati
avrà una trama di conferma di 4 byte, non una risposta più lunga con dei
dati). Occorre aggiungere che questa lunghezza massima è relativa solo ai comandi
originati dall'host. I comandi generati dalla scheda (stato dei pulsanti) saranno
composti da un comando di 5 byte (comando più un parametro) ed una conferma di
4 byte, quindi 9 byte in totale. Se viene inviato un comando dall'host e, prima che
arrivi la risposta, arriva un comando dallo slave, avremo un massimo di 514 + 9 = 523
caratteri. A 9600 baud (tenendo in considerazione anche i bit di start e di stop)
questo porta a 544 mS. Utilizzeremo quindi un timeout di 660 mS (da 605 a 660 mS) che
garantisce un sufficente margine. Se questo timeout scade senza che sia giunta la risposta,
considereremo che sia avvenuto un errore e il comando dovrà essere ritrasmesso,
per un massimo di 5 volte.
- È possibile che entrambe le parti inizino a trasmetter un comando simultaneamente.
In questo caso la conferma o risposta verrà ritardata fino al termine della trasmissione
della trama corrente, ma questo ritardo non è tale da far scattare il meccanismo della
ritrasmissione.
Sviluppo del protocollo
Questo protocollo si sviluppa su due livelli.
- : macchina a stati SerialTx, macchina a stati SerialRx
- : macchina a stati Transmitter,macchina a stati Receiver
Implementazione su 8052
Entrambe le macchine a stati del primo livello saranno implementate nella routine
di risposta all'interrupt seriale
- SerialTx parte quando un kickoff (un byte 7E hex)
è inviato dal livello superiore; legge il pacchetto da inviare da un buffer,
(scelto in base al tipo di invio: comando o risposta) e lo trasmette, calcolando
nel contempo il checksum, rispettando le regole di trasparenza, quindi invia il
chacksum ed il 7E hex di chiusura.
- SerialRx parte quando viene ricevuto un byte di flag, di valore 7E hex; riceve
una trama, ricostruendo i caratteri mascherati e calcolando il checksum; alla ricezione
del flag di chiusura, verificherà il checksum e, se sarà corretto, segalerà
all'opportuno livello superiore, in base al tipo di pacchetto ricevuto, l'avvenuta ricezione,
attivando un flag.
Nel secondo livello, il ricevitore è implementato nella procedura in foreground, in
mainera procedurale e non come automa, mentre il ricevitore è implementato nella
procedura di risposta all'interrupt del timer 0.
- Il trasmettitore è attivato settando un flag. Invia semplicemente
un kickoff (se necessario) per avviare SerialTx ed attende 495 mS una
risposta. Se, durante questo tempo, SerialRx non avvisa della ricezione di una
risposta, il trasmettitore reinvia il comando. Il trasmettitore si ferma o
quando è ricevuta una risposta o quando sono state effettuate 5 ritrasmissioni.
- Il ricevitore è attivato quando SerialRx attiva il flag di comando ricevuto.
Esamina il byte di comando ed esegue l'azione relativa, quindi invia la conferma o risposta
tramite SerialTx. L'azione non deve richiedere troppo tempo, in quanto altrimenti potrebbe
scattare il timeout del trasmettitore dell'altra parte.
Implementazione su PC
Dobbiamo gestire indipendentemente tre flussi:
- Ingresso seriale
- Uscita seriale
- Ingresso da tastiera (stdin)
ed inoltre dobbiamo gestire dei timeout.
Per ottenere tutto questo occorre utilizzare la funzione select.
Comandi
Dall'Host
- Richiesta stato Tasti
- Codice Comando: hex 10
- Parametri: Nessuno
- Risposta/Conferma: hex 90, seguito dal byte con lo stato dei tasti
- Descrizione: questo comando consente di richiedere alla scheda lo stato attuale dei tasti.
Il byte inviato come risposta conterrà, nei bit bassi, lo stato nuovo dei pulsanti (0 -> rilasciato, 1 -> premuto) per
ciascuno dei quattro pulsanti presenti sulla scheda del display.
- Reset Display
- Codice Comando: hex 52
- Parametri: Nessuno
- Risposta/Conferma: Conferma
- Descrizione: Questo comando cancella e resetta il contenuto del display.
- Scrittura Caratteri su Display
- Codice Comando: hex 21
- Parametri: colonna (0..40) espressa in celle di carattere, riga (0..1), caratteri da scrivere (non terminati
con NULL)
- Risposta/Conferma: Conferma
- Descrizione: scrive i caratteri indicati, a partire dalla colonna indicata, nella riga indicata.
I caratteri sono scritti in una cella di 8 righe e 6 colonne. Se i caratteri inviati sono più di quelli
che stanno nella riga corrente, i caratteri in eccesso sono scartati.
- Scrittura Pixel su Display
- Codice Comando: hex 22
- Parametri: colonna (0..249) espressa in pixel, riga (0..1), colonne di pixel da scrivere
- Risposta/Conferma: Conferma
- Descrizione: scive le colonne di pixel inviate, a partire dalla colonna indicata, nella riga indicata.
Ogni colonna di pixel è costituita da otto bit, corrispondenti ad otto pixel. Il bit più significativo
corrisponde al pixel più in basso, il meno significativo a quello più in alto, 0 corrisponde a pixel spento,
1 a pixel acceso. Se le colonne inviate sono più di quelle
che stanno nella riga corrente, le colonne in eccesso sono scartate.
- Richiesta Stringa Versione
- Codice Comando: hex 44
- Parametri: Nessuno
- Risposta/Conferma: hex C4, seguito dalla stringa di caratteri null terminated (stile C)
contenete la denomiunazione e versione del software.
- Descrizione: questo comando consente di richiedere alla scheda una stringa di presentazione.
La stringa sarà una stringa stampablie, contenete, nell'ordine, il nome del prodotto, un '-',
il nome del produttore/programmatore, un ':', la stringa della versione 'v.M,m', dove M è il
numero maggiore di revisione, una cifra, e m è il numero minore di revisione, sempre una cifra.
Dalla scheda
- Cambiamento stato Tasti
- Codice Comando: hex 16
- Parametri: il byte contenete il nuovo stato dei tasti, nei quattro bit bassi
- Risposta/Conferma: Conferma
- Descrizione: questo comando viene inviato dalla scheda tutte le volte che rileva un
cambiamento nello stato dei tasti (pressione o rilascio). Il byte inviato come parametro
conterrà, nei bit bassi, lo stato nuovo dei pulsanti (0 -> rilasciato, 1 -> premuto) per
ciascuno dei quattro pulsanti presenti sulla scheda del display. La scheda gestirà la logica
di antirimbalzo, inviando un evento appena viene rilevato un cambiamento nello stato dei tasti, quindi
attendendo 100mS prima di rilevare di nuovo lo stato dei tasti. In questo modo, al nuovo rilevamento
dello stato il transitorio del tasto si sarà esaurito.
[Scarica il tarball con il programma per la scheda]
[Home Page dell'ITIS "Fermi"]
[Indice Quinta]
[Precedente]
[Successivo]
© Ing. Stefano Salvi - Released under GPL licence
|