|
Esercizio# 7 - Migliorare l'oggetto - Output.spin
In questo esempio viene modificato e migliorato solo il file oggetto OUTPUT.SPIN.
|
{{ Output.spin }}
VAR
long Stack[9] 'Assegna spazio necessario per lo stack
byte Cog 'Memorizza l'ID del cog in funzione
PUB Start(Pin, Delay, Count): Success
{{Avvia un nuovo processo di lampeggio in un nuovo cog, ritorna TRUE se ok}}
Stop
Success := (Cog := cognew(Toggle(Pin, Delay, Count), @Stack) + 1)
PUB Stop
{{Arresta il processo di lampeggio fermando il cog}}
if Cog
cogstop(Cog~ - 1)
PUB Active: YesNo
{{Ritorna TRUE se il processo è attivo, altrimenti ritorna FALSE.}}
YesNo := Cog > 0
PUB Toggle(Pin, Delay, Count)
{{Inverte il Pin, tante volte come in Count e con ritardo in Delay (clock cycles).}}
Se Count = 0, inverte il Pin per sempre.}}
dira[Pin]~~ 'Imposta il registro di direzione I/O
repeat 'Ripeti il codice..
!outa[Pin] 'Inverti il pin I/O
waitcnt(Delay + cnt) 'Attendi i cicli macchina in Delay
while Count := --Count #> -1 'Ripeti finché Count non è uguale a 0 (make min -1)
Cog~ 'Cancella la variabile Cog
|
Negli esempi precedenti non era stato previsto un metodo per arrestare il lampeggio di un led, ma si doveva attendere il termine della sua esecuzione. In questo esempio invece vengono aggiunti due nuovi metodi all'oggetto "Output", uno chiamato Start e uno chiamato Stop. Il primo (Start) esegue l'avvio di un nuovo cog ed il lampeggio del led collegato al pin richiesto. Il secondo (Stop) termina semplicemente l'operatività del cog terminandone di conseguenza anche l'esecuzione del suo programma. Nel gruppo di dichiarazione delle variabili (VAR) è stata aggiunta una variabile chiamata Cog, che avrà il compito di memorizzare quanti Cog sono attivi. Entrambe le variabili (Stack e Cog) sono "Pubbliche" all'interno dell'oggetto OUTPUT.SPIN, ciò significa che la loro modifica all'interno dei metodi (PUB o PRI) avranno effetto solo all'interno dell'oggetto OUTPUT.SPIN.
Nel metodo 'Start':
E' stato aggiunta la possibilità di far ritornare un valore (: Success) che riporta il risultato (positivo/negativo) dell'operazione di start di un nuovo Cog. A causa del fatto che nel 'propeller' i Cog non sono infiniti, ma ne abbiamo un numero limitato, è buona cosa sapere se l'avvio di un nuovo Cog è avvenuto con successo.
Per ciascun metodo PUB/PRI, il ritorno di un valore è sempre di tipo Long (4 bytes), ma in questo caso, il valore di ritorno sarà di tipo booleano (true/false).
Il metodo Start esegue due cose: Inizialmente esegue lo STOP del Cog (metodo Stop), questo è stato aggiunto giusto nel caso che il metodo START sia stato eseguito più volte (senza eseguire lo STOP), così da creare confusione tra i Cog ed eventualmente creare sovrascritture indesiderate nell'area dello STACK. Successivamente avviene lo Start con l'esecuzione della riga: Success := (Cog := cognew(Toggle(Pin, Delay, Count), @Stack) + 1)
Analizziamo brevemente questa riga: La prima cosa da dire è che è molto simile a quella dell'esercizio precedente, ma questa volta l'istruzione cognew è racchiusa all'interno di un'altra espressione. Il risultato di tutto è che la variabile Success assume un valore compreso tra 0 e 7 se l'operazione di start del Cog è avvenuta correttamente, altrimenti assumerà il valore -1 (Cog non disponibile). Invece la variabile Cog assumerà l'ID del cog che è entrato in esecuzione. Il metodo che eseguirà il nuovo Cog è ovviamente il metodo Toggle, come nell'esercizio precedente. Una cosa da notare è l'operatore di assegnazione ':=', il quale assume una sintassi leggermente differente rispetto ai linguaggi più comuni. Ricordiamo che invece i valori per le costanti devono essere assegnati solamente con il simbolo '='.
Nel metodo Stop:
viene arrestato il Cog se già in esecuzione. Infatti troveremo all'interno di questo metodo una IF che condiziona l'esecuzione dell'istruzione COGSTOP. Se la variabile Cog (ricordate che è stata impostata durante l'esecuzione di COGNEW?) è maggiore di zero, significa che almeno un COG è già in esecuzione. Quindi un valore di Cog superiore/diverso a zero equivale a TRUE, mentre un valore uguale a zero equivale a FALSE. Nella nostra IF, l'istruzione COGSTOP viene eseguita se la variabile Cog ha un valore diverso da zero (almeno un Cog è in esecuzione). Ora passiamo alla linea cogstop(Cog~ - 1). Nell'istruzione COGSTOP, è necessario indicare l'ID del cog che desideriamo arrestare. Avendo già a disposizione una variabile che contiene il valore dell'ultimo Cog avviato, possiamo dire al programma di fermare l'esecuzione del cog (sottraendo 1 dal suo valore iniziale), e successivamente 'azzerare' la variabile Cog. Questa ultima cosa avviene con l'istruzione 'Cog~' dove il simbolo '~' è un POST-OPERATOR, il che significa che l'operazione di 'azzeramento' della variabile Cog avverrà per ultima, dopo che viene sottratto '1' dal suo valore originale. Riassumendo, la sequenza è: Arresta il cog con ID = variabile Cog meno 1, successivamente imposta a zero la variabile Cog.
Nel metodo Active:
Viene semplicemente restituito un valore TRUE/FALSE se la variabile Cog è maggiore o uguale a zero. Il metodo può essere utile a capire se il cog è in esecuzione.
Nel metodo Toggle:
Sono state effettuate piccole ma significative variazioni. All'ultima linea troviamo l'istruzione Cog~ la quale 'azzera' la variabile Cog al termine dell'esecuzione del lampeggio. Questa serve a 'ricordare' che l'esecuzione del programma nel cog è teminata, quindi il Cog si metterà in uno stato dormiente fintanto che non ritorni in esecuzione con una nuova istruzione COGNEW. Se non forzassimo il valore di questa variabile a zero, i metodi START e ACTIVE potrebbero non capire che il lavoro in questo Cog è terminato, credendo che esso sia ancora impegnato nell'esecuzione di TOGGLE.
|