• Non ci sono risultati.

Capitolo 5

N/A
N/A
Protected

Academic year: 2021

Condividi "Capitolo 5"

Copied!
20
0
0

Testo completo

(1)

Capitolo 5

[1], [7], [15]

I comandi

In questo capitolo verrà trattata la sezione relativa ai comandi, che è stata introdotta per gestire la macchina tramite la pressione di tasti esterni e tramite l’impostazione di deviatori. Senza questa parte di codice il sistema non potrebbe funzionare se non collegato col sistema di sviluppo, ovvero l’emulatore e l’ambiente di sviluppo Code Composer, gestendo il flusso di istruzioni a run time tramite l’impostazione manuale dei flag interessati. L’aver operato in questo modo ha reso possibile il controllo del corretto funzionamento della parte relativa alle procedure di registrazione e riproduzione svincolandolo dal debug della parte relativa alla gestione comandi.

5.1 Configurazione del DSP per la gestione dei comandi

Innanzitutto per la gestione dei comandi si è deciso di utilizzare l’Host port HPI-8, impostandolo come general-purpose input/output (GPIO) pin. Quest’operazione si effettua mettendo a GND il pin del DSP HPIENA, che nella scheda sulla quale si è realizzato il debug era stato lasciato flottante. Infatti, come si apprende dal data-sheet, perché l’HPI-8 sia settato come detto è necessario che il pin HPIENA sia letto a livello logico basso durante la fase di reset.

(2)

mapped) GPIOCR di conseguenza. Nella seguente figura si vede come sono definiti i campi di questo registro:

Figura 1: GPIOCR

Il bit TOUT1 viene impostato a 0, perché in questo modo viene disabilitata l’uscita del timer 1 sull’HINT pin; comunque questo timer non viene utilizzato nella nostra applicazione. Per quanto riguarda i bit di direzione DIR7-DIR0, quelli che vengono configurati con uno zero logico indicano che il corrispondente segnale dell’HPI-8 è un ingresso. Quindi per la nostra applicazione è necessario scrivere in tale campo del registro GPIOCR un byte di tutti zeri, come si vede dall’istruzione nel codice:

asm(" STM #0000h, GPIOCR");//Pin HD7-0 configured as inputs

Lo stato dei pin GPIO (HD7-HD0) può essere monitorato usando i bit del general purpose I/O status (GPIOSR). Quando uno dei pin HDx è configurato come un ingresso, il corrispondente bit nel GPIOSR può essere letto per determinare il valore logico rilevato su questo pin. I bit IO7-IO0 rispecchiano lo stato dei pin HD7-HD0. Se questi ultimi sono configurati come ingressi (come nel caso del nostro progetto), i bit IO7-IO0 “latchano” il valore logico (1 o 0) di questi pin di ingresso.

(3)

Figura 2: GPIOSR

5.2 I Command e i Setting

Con tale implementazione è possibile gestire i comandi dall’esterno tramite questi pin, e l’assegnazione di ognuno di questi al tipo di comandi viene fatta nel modo seguente:

• HD7 ⇐ free (su questo pin non mando nessun comando) • HD6 ⇐ Pause (Command)

• HD5 ⇐ Stop (Command) • HD4 ⇐ Start (Command) • HD3 ⇐ Sample rate (Setting) • HD2 ⇐ Rec/Play (Setting) • HD1 ⇐ Repeat (Setting)

• HD0 ⇐ Reset conditions (Setting)

Viene fatta per ogni pin la distinizione tra Command e Setting. Per Command si intendono quei segnali come lo Start, lo Stop e il Pause, che gestiscono l’esecuzione del codice nel suo complesso, e non le modalità di funzionamento della macchina che sono gestite dai Setting. Questa differenziazione ha una vera e propria rispondenza hardware in quanto per inviare comandi si è optato per l’utilizzo di tasti che

(4)

è premuto il livello logico risultante è alto per la presenza di una resistenza di pull up. Viceversa per impostare i Setting, che definendo delle configurazioni di operatività della macchina non vanno continuamente modificati, almeno per un normale utilizzo, sono stati previsti dei deviatori che portano sul pin un livello logico alto o basso; in questo caso non sono state utilizzate resistenze di pull up.

Si dà ora qui di seguito una breve descrizione di quello che fa ogni singolo Command e di quello che implica ogni impostazione (Setting). Le specifiche di questi comandi sono state stabilite dalla ditta che ha commissionato il progetto alla Seed.

5.2.1 I Command

Pause ⇐ Con tale Command si impone una momentanea interruzione delle operazioni di trasferimento dati. Se il sistema era in riproduzione si interrompe l’estrazione dei dati dalla flash card e dalla SRAM e le uscite si silenziano. Cosa simile accade quando siamo in registrazione: si interrompe momentaneamente il trasferimento dati dal DSP verso la SRAM e dalla SRAM verso la flash card e si ammutoliscono le uscite.

Stop ⇐ Questo Command ovviamente serve per interrompere l’esecuzione che era in atto, riproduzione o registrazione che fosse. Una volta premuto il pulsante di Stop il processo si interrompe e le uscite si silenziano. Da questo stato la macchina può uscire, oltre che naturalmente tramite uno spegnimento o un reset, soltanto con la pressione del Command di Start. In seguito a questo il processo, registrazione o riproduzione che fosse, riprende in ogni caso dall’inizio della flash card, e non dal punto al quale si era arrivati prima della pressione del tasto Stop.

Start ⇐ Tramite questo Command si attiva il processo selezionato con i Setting, ovvero registrazione o riproduzione. Ad ogni pressione di questo tasto

(5)

l’esecuzione ricomincia comunque dall’inizio della flash card, anche se questo tasto viene premuto mentre il sistema è già in fase di esecuzione.

5.2.2 I Setting

Sample rate

Questa impostazione permette di scegliere la frequenza di campionamento del processo che si ha intenzione di eseguire. Come già accennato nell’introduzione a questo lavoro di tesi, è possibile scegliere due diverse frequenze di campionamento, 39062.5 Hz e 24414.06 Hz, dove l’utilizzo della prima permette una maggiore qualità sonora per la più ampia banda audio gestibile, in virtù del teorema di Nyquist, mentre l’utilizzo dell’altra ha il vantaggio di permettere una maggiore durata di registrazione e riproduzione per le flash card, al prezzo di una lieve perdita in qualità audio dovuta alla riduzione della banda.

Rec/Play

Tramite questo Setting si comunica alla macchina quale deve essere il processo che si vuole intraprendere, se di riproduzione o di registrazione.

Repeat

Tale Setting ha validità solo in fase di riproduzione e imposta il sistema in modo tale da far riprendere la riproduzione all’inizio della flash card una volta arrivati in fondo, senza necessità di ripremere il tasto Start. Ovviamente non è valido in fase di registrazione perché altrimenti arrivati in fondo alla flash card, dopo aver riempito tutti i settori disponibili, si continuerebbe a registrare dall’inizio e quindi scrivere campioni anche sui primi settori della flash card, sui quali sono già stati memorizzati dei campioni che magari non si voleva cancellare.

(6)

Tramite questo Setting si stabilisce se all’accensione (o equivalentemente dopo la pressione del tasto reset) l’esecuzione (registrazione o riproduzione che sia) debba cominciare automaticamente o si debba attendere l’invio del Command di Start.

5.2.3 Meccanismo di protezione

Nel codice è stato implementato un meccanismo per il quale non è possibile modificare l’impostazione dei Setting: Sample rate e Rec/Play in fase di esecuzione, o meglio: una modifica di uno di questi Setting in fase di esecuzione porta ad una immediata interruzione di quest’ultima, sortendo lo stesso effetto della pressione del tasto Stop. Questo “meccanismo di protezione” ha un duplice scopo:

• Salvaguardare il sistema da eventuali modifiche involontarie di questi Setting. In effetti si è considerato il fatto che una modifica della frequenza di campionamento o il cambio tra registrazione e riproduzione durante l’esecuzione non possano essere considerate come operazioni valide, e di conseguenza si è implementato tale meccanismo, anche per proteggere dati preregistrati da una eventuale involontaria cancellazione.

• Durante la fase di debug si sono riscontrati dei problemi provando a cambiare, in piena fase di Start, da registrazione a riproduzione e viceversa, oppure modificando la frequenza di campionamento. Questo perché nel passaggio tra queste modalità di funzionamento i puntatori, tramite i quali si gestisce il flusso di dati tra la flash card e la SRAM e tra la SRAM e il DSP, potrebbero non venire inizializzati correttamente, a seconda della zona del buffer di SRAM in cui si trovano, facendo quindi andare in tilt il sistema. L’unica soluzione è quindi quella di reinizializzare questi puntatori come sono alla prima esecuzione del programma, esattamente quello che succede premendo il pulsante di Start. In questo modo non si hanno più problemi di puntatori che non puntano

(7)

correttamente. Per forzare quindi un processo di reinizializzazione del sistema è sufficiente mandarlo in Stop, perché come si è detto da questo stato si esce comunque ripassando per quei comandi che inizializzano correttamente i puntatori.

Qui di seguito verranno trattati i problemi e le rispettive soluzioni che si sono incontrati nella sezione relativa alla gestione comandi, facendo costantemente riferimento al codice.

5.3 Gestione comandi: il codice

Innanzitutto vengono inizializzati dei flag, quando siamo ancora nella parte di inizializzazioni, per far sì che non appena finita questa fase ed entrati nella fase operativa, cioè nel corpo del while( ), il sistema si trovi nella stessa condizione nella quale si troverebbe se fosse inoltrato il Command di Stop e non si fosse ancora compiuta alcuna lettura o scrittura. I flag che vengono toccati sono, come si vede nella seguente sezione di codice:

// Init Flash's commands flags

asm(" ld #00h, a");

asm(" stl a, Flag_first_wr_rd");

asm(" stl a, Flag_start_stop"); //Flag_start_stop=0 Significa STOP asm(" ld #01h, a");

asm(" stl a, Com_start_mask");

Il flag Com_start_mask ha la funzione di far sì che il Command di Stop sia inoltrato solo la prima volta che il pin sul quale è collegato il tasto dello Stop viene letto a livello logico basso, e non tutte le volte per tutta la durata del tempo nel quale il pulsante di Stop rimane premuto. Questo meccanismo verrà illustrato meglio più avanti.

(8)

5.3.1 Aggiornamento dello status dei comandi di ingresso

Dopo questa prima fase di inizializzazione nella quale si transita sia all’accensione, sia dopo l’invio di un reset tramite il pulsante esterno, sia dopo che è stata rilevata l’assenza della flash card (si veda in merito il precedente capitolo dove sono esplicati i diagrammi di flusso), si arriva a quella parte di codice che viene eseguita continuamente, nel corpo del while( ).

Essendo presente in questa sezione un polling su un registro della porta seriale che avvisa quando è stato ricevuto un nuovo dato dall’esterno, si può dire che tutto il blocco di istruzioni viene fatto ogni volta che viene ricevuto un campione, sia che questo provenga dal canale sinistro o dal canale destro; i campioni infatti si distinguono tra destro e sinistro tramite il meccanismo di test sul BIO come già visto nel capitolo dedicato all’hardware, dopodiché vengono immagazzinati esattamente con la stessa procedura. Quindi il blocco di istruzioni si ripete con una cadenza che è pari al doppio della frequenza di campionamento, ed è con tale cadenza che si va a testare l’HPI-8 per vedere se ci sono stati dei cambiamenti nello status dei comandi.

Tutto ciò è vero finché non si inoltra un Command di Pause o di Stop. In questo caso, tramite un opportuno test sui flag, la fase di acquisizione del dato dal codec, per copiarlo nella variabile di ingresso, viene saltata e con essa viene anche saltata la fase in cui si opera un polling sul registro che avvisa quando è stato ricevuto un dato in ingresso dalla porta seriale. Così facendo si eliminano i tempi di attesa per questi dati e quindi l’insieme di istruzioni presenti nel while( ) si ripete non appena si è arrivati in fondo al corpo del while( ) stesso, facendo sì che la cadenza con la quale si va a verificare lo stato dei comandi di ingresso sia decisamente superiore al doppio della frequenza di campionamento. La parte di codice relativa ai test di cui si è parlato è:

// Salto la parte relativa all'in/out samples se sono in stop o pausa

asm(" ld Flag_start_stop, a");

asm(" bc START_OF_PROCESS, aeq");//Flag_start_stop=0 vale STOP asm(" ld Com_pause, a");

(9)

asm(" bc START_OF_PROCESS, aeq");//Se Com_pause=0 salto

… (parte relativa all’acquisizione dei campioni) …

//**************************************************************** //**************************************************************** // PROCESS ON DATA * //**************************************************************** //**************************************************************** asm("START_OF_PROCESS");

5.3.2 Acquisizione dello status dei comandi di ingresso

L’operazione che si compie è quella di copiare il contenuto del registro GPIOSR (che è memory mapped) in una variabile e di lavorare con quella, visto che durante il processo di acquisizione lo status dei comandi di ingresso potrebbe cambiare e quindi se si richiamasse più volte il registro GPIOSR per settare i flag che si usano per la gestione comandi potrebbero venir letti degli status differenti tra una lettura e l’altra del registro, stati che non essendo coerenti tra loro potrebbero portare ad una inizializzazione errata dei flag e quindi ad un funzionamento non corretto. Copiare GPIOSR in una variabile una sola volta ad acquisizione per poi settare i flag tramite quella variabile elimina il problema enunciato.

Dopodiché vengono selezionati tramite una maschera i bit che interessano (cioè la parte bassa del registro) e tramite questi si inizializzano i flag, shiftando opportunamente la variabile scritta col contenuto del registro GPIOSR e settando i flag interessati una volta evidenziato con un AND il bit del registro relativo al settaggio di quel flag. Il codice che compie questa operazione viene riportato qui di seguito:

(10)

//**************************************************************** // Lettura status ingresso comandi * //****************************************************************

asm(" ldm GPIOSR , a"); asm(" and #00ffh , a"); asm(" stl a, gpiosr_reg");

asm(" and #0001h , a");//Setting0=wait for start=0,Autostart=1 asm(" stl a, Set_autostart");//Inizializzo flag start

asm(" ld gpiosr_reg, -1, a");

asm(" and #0001h , a");//Setting1=Play one time=0,Repeat forever=1 asm(" stl a, Set_repeat");

asm(" ld gpiosr_reg, -2, a");

asm(" and #0001h , a");//Setting2 = Rec=0,Play=1 asm(" stl a, Set_rec_play ");

asm(" ld gpiosr_reg, -3, a");

asm(" and #0001h , a");//Setting3 = Sample rate 22KHz=0,44Khz=1 asm(" stl a, Set_sample_rate");

asm(" ld gpiosr_reg, -4, a");

asm(" and #0001h , a");//Command4 = Start (0 pulse) asm(" stl a, Com_start");

asm(" ld gpiosr_reg, -5, a");

asm(" and #0001h , a");//Command5 = Stop (0 pulse) asm(" stl a, Com_stop");

asm(" ld gpiosr_reg, -6, a");

asm(" and #0001h , a");//Command6=Pause=0,Continue play=1 asm(" stl a, Com_pause");

5.3.3 Aggiornamento dei flag e gestione dei Setting

Tramite il settaggio dei flag considerati si vanno a comandare altri flag che erano nella versione preesistente del codice, quando ancora non era stata fatta la sezione comandi, e si usavano per gestire manualmente l’esecuzione del codice. Infatti si otteneva ciò impostando via software, tramite l’emulatore, la frequenza di campionamento, se registrare o riprodurre, ecc.

Vengono implementati in questo frangente due meccanismi molto importanati:

• Il meccanismo dell’autostart, ovvero l’avvio automatico del processo di scrittura o lettura della flash card immediatamente dopo l’accensione o dopo il reset.

(11)

• Protezione da eventuale modifica dei Setting Sample rate e Rec/play durante la fase di esecuzione del processo di riproduzione o registrazione.

Nel seguente spezzone di codice viene esaminata la gestione dei flag per la scelta tra registrazione o riproduzione , avendo come ingresso il Setting Rec/Play proveniente dal registro GPIOSR.

Si testa se il processo di lettura/scrittura in questione sia il primo dall’accensione (o dal reset) tramite un flag che tiene conto di questo fatto e in caso negativo (ovvero non è la prima lettura/scrittura dall’accensione) si va a verificare che il Setting Rec/Play non sia cambiato rispetto al suo ultimo valore assunto. Questo si fa perché ovviamente non si può sapere come sarà impostato il Setting del Rec/Play all’accensione e quindi, impostandolo ad un certo valore di default da inizializzazione della variabile, si potrebbe sempre incappare, nella prima esecuzione, in un valore diverso da quello settato per default e ciò imporrebbe un’arresto dell’esecuzione, ovvero uno Stop, che sarebbe in contrasto con un’eventuale settaggio a 1 logico del Setting Autostart. Se, nel caso non sia la prima scrittura o lettura, il Rec/Play è cambiato, si deve verificare qual’era lo stato precedente, se di esecuzione (Start) o di Stop. Se si era nel bel mezzo di un processo di lettura o scrittura allora significa che, per il meccanismo precedentemente illustrato, il sistema deve essere posto in arresto, e ciò si ottiene simulando la pressione del tasto Stop tramite il settaggio del Flag_start_stop a 0 e l’azzeramento delle uscite. Se invece già ci si trovava in fase di Stop non succede nulla, a parte la modifica del Setting Rec/Play come richiesto dall’invio del comando. La parte di codice relativa a questa sezione è la seguente:

// Test. Se cambio impostazione Recording/Playing in fase di START // vado in STOP. Ciò non vale se sono alla prima scrittura/lettura

asm(" ld Flag_first_wr_rd, a"); // Se Flag_first_wr_rd = 1 asm(" bc Test_Set_rec_play_done, aeq");// NON è la prima scrit asm(" ld Set_rec_play, a");

asm(" sub Set_rec_play_prec, a");

asm(" bc Test_Set_rec_play_done, aeq");//Set_rec_play non è modif asm(" ld Flag_start_stop, a");

(12)

asm(" b Azzera_Out");//Se non ero in STOP mi fermo

asm("Test_Set_rec_play_done"); asm(" ld Set_rec_play, a"); asm(" stl a, Set_rec_play_prec");

// Impostazione Recording/Playing

asm(" ld Set_rec_play, a"); //Record (Scrive Flash)=0 //Play (Legge Flash)=1 asm(" stl a, Rd_Wr_Flash");

Ed un diagramma di flusso che rende conto di quanto descritto sopra ed eseguito dal codice è il seguente: SI NO NO SI NO SI “Azzera_Out” È la prima lettura/scrittura nella flash? Sezioni precedenti Il setting Rec/play è stato modificato?

Si era in una fase di lettura/scrittura?

Si interrompe la lettura/scrittura simulando la pressione del tasto di

stop tramite l’impostazione del Flag_start_stop=0

“Test_Set_rec_play_done” Assegno il valore del setting Set_rec_play al flag che si testa a

(13)

La gestione del flag relativo all’impostazione della frequenza di campionamento viene fatta nello stesso identico modo nel quale è stata fatta quella per il Setting Rec/play, per le somiglianze nel meccanismo di gestione, come è stato spiegato più volte precedentemente, e quindi non viene riportata.

Il Setting Repeat, che come già detto riguarda esclusivamente la fase di riproduzione, ha una gestione ovviamente diversa da quella vista per Rec/Play e Sample rate, i quali interagivano con il flag Flag_first_wr_rd, mentre invece il Repeat non ne ha bisogno. Si riporta qui di seguito la sequenza di comandi che riguarda la gestione di questo flag:

// Se arrivo qui LBA_0to27==Num_Sectors_of_Flash

// Test sul Set_repeat per vedere se devo rileggere dall'inizio

asm("Test_Set_repeat_rd"); asm(" ld Set_repeat, a");

asm(" bc Init, aneq");//Se Set_repeat=1 allora riparto da capo asm(" ld #00h, a");//Per fermarmi se sono in fondo e Set_repeat=0 asm(" stl a, Flag_start_stop");//Flag_start_stop=0 Vale STOP

asm("Azzera_Out");

asm(" ld #Left_In, dp"); asm(" ld #00h , a"); asm(" stl a, Left_Out"); asm(" stl a, Right_Out");

Una volta letti tutti settori della flash card, se si trova che il Setting Set_repeat vale un 1 logico, allora si fa ripartire l’esecuzione del codice dalla label “Init”. Questo punto del codice è stato messo poco prima del while( ) e contiene tutte quelle informazioni che servono a reinizializzare correttamente i puntatori e i flag perché si ricominci con una nuova riproduzione dei dati presenti nella flash card. Infatti è da questo medesimo punto che ricomincia l’esecuzione del codice quando si inoltra il Command Start, quindi

Sezione successiva: Gestione del setting

(14)

del tutto identico alla pressione del tasto Start. Se il Setting Set_repeat non è impostato per la ripetizione allora l’arrivo in fondo, dopo aver riprodotto tutti i settori della flash, implica una conseguente interruzione della riproduzione e il sistema si porta nello stato di Stop scrivendo zero nel Flag_start_stop. Dopodiché vengono silenziate le uscite tramite l’invio al codec di campioni che valgono 00h sia per il canale destro che per il sinistro.

5.3.4 Aggiornamento dei flag e gestione dei Command

Nella sezione di codice immediatamente successiva alla fase di acquisizione dei dati dalla porta seriale e invio a quest’ultima dei dati da portare in uscita al codec, si ha la sezione relativa alla scelta tra scrittura e lettura. Le poche righe di codice che si occupano di questa operazione, peraltro di fondamentale importanza, non hanno bisogno di spiegazioni:

asm("START_OF_PROCESS");

// Test su Read/Write Flash, Playing/Recording

asm(" ld #Rd_Wr_Flash, dp"); asm(" bitf Rd_Wr_Flash, #01h"); asm(" bc Read_Flash, tc");

asm("Write_Flash");

Dopodiché il codice prosegue con la parte dedicata alla scrittura. Come già accennato la parte dedicata alla registrazione e la parte dedicata alla riproduzione sono completamente separate all’interno del codice. Questo perché, benché le parti siano molto simili, la gestione di entrambe tramite la stessa sezione di codice sarebbe stata molto più complicata, con più flag e test da compiere. Però per quanto riguarda la sezione comandi la parte relativa alla scrittura è esattamente identica a quella relativa alla lettura e quindi in questa sede verrà trattata solo la parte relativa alla scrittura.

(15)

5.3.5 Comandi nel processo di registrazione

La gestione dei comandi viene fatta all’interno della sezione contenente il processo vero e proprio di memorizzazione dei dati. Di seguito si riporta un diagramma di flusso generale che spiega come viene gestita questa parte:

SI

NO

“Write_Flash”

Test e aggiornamento dei flag (prima della proc)

Si è nello stato di stop?

Scrittura dei dati nel buffer di SRAM e nella

Flash Card, aggiornamento puntatori e

test per vedere se si è arrivati in fondo

“No_Card_Detected_wr”

Test e aggiornamento dei flag (dopo la proc)

(16)

SI

NO

È importante notare che a questo livello non vi è differenza, nel flusso di comandi eseguiti, tra l’inoltro di un Command di Pause e l’inoltro di un Command di Stop. In entrambi i casi infatti si salta completamente la procedura che scrive i dati nel buffer di SRAM e nella flash card. In entrambi i casi inoltre non vengono aggiornati i puntatori con i quali si gestisce il meccanismo di scrittura descritto nel capitolo precedente perché il processo che viene saltato contiene anche i test che aggiornano questi puntatori. L’unica vera grande differenza è che al rilascio del Command Pause l’esecuzione riprende dal punto in cui era, in dipendenza dello stato del Flag_start_stop. Ovvero se ci si trovava in uno stato di Stop (Flag_start_stop == 0) al rilascio del Command Pause si resta in questo stato (in pratica si è schiacciato il tasto Pause quando il sistema non stava ancora registrando). Se invece si era in registrazione, questa prosegue dal punto in cui era stata interrotta, avendo lasciato inalterato il valore dei puntatori. Invece per quanto riguarda il Command di Stop questo opera nello stesso modo del Command Pause, però imposta il Flag_start_stop a zero. Da questo stato la macchina può uscire solo tramite la pressione del Command Start, e quindi è a questo punto che si reinizializzano i puntatori e flag giusti per far reiniziare la scrittura all’inizio della flash card.

Si è nello stato di

stop o in pausa? “Azzera_Out”

Preparazione I/O diretto per sentire quello che si

(17)

Test e aggiornamento dei flag prima della procedura

Riportiamo qui di seguito la parte di codice relativa al test e aggiornamento dei flag prima della procedura vera e propria di scrittura:

// Test relativi ai comandi

asm(" ld Com_pause, a");

asm(" bc Azzera_Out, aeq"); // Se in Pause vado a Azzera_out

asm(" ld Flag_start_stop, a");

asm(" bc Tests_done_wr, aneq"); // Flag_start_stop=1 Vale START asm(" ld Flag_first_wr_rd, a"); // Se Flag_first_wr_rd=1 NO 1 scrit asm(" bc No_Card_Detected_wr, aneq");

asm(" ld #01h, a");

asm(" stl a, Flag_first_wr_rd"); asm(" ld Set_autostart, a");

asm(" bc No_Card_Detected_wr, aeq"); // Se Set_autostart=0 fermo!

asm(" ld #01h, a"); // Se Set_autostart è a 1 go! asm(" stl a, Flag_start_stop"); // Flag_start_stop=1 Vale START

asm("Tests_done_wr");

Se ci si trova in Pause, ovvero il Command Com_Pause viene rilevato a livello basso, si va direttamente in fondo al codice dove troviamo l’azzeramento delle uscite, ovvero la sezione etichettata: “Azzera_Out”, e il salto all’inizio del corpo del while( ), il tutto senza compiere nessuna operazione. Poi si vede che, sulla falsariga di quanto visto per i Setting, se vi era un’esecuzione in atto questa continua perché in questa sezione il Flag_start_stop viene solo testato e non modificato, o meglio non è modificato dai Command esterni. Se non vi era un’esecuzione in atto si va a testare il Setting Flag_first_wr_rd per verificare che non sia ancora stata effettuata una scrittura. In caso affermativo si testa Set_autostart e se il sistema è stato impostato per partire in automatico all’inizio viene modificato il Flag_start_stop mettendolo ad 1 logico.

(18)

Test e aggiornamento dei flag dopo la procedura

Dopo la parte relativa alla scrittura si trova un’altra sezione relativa all’aggiornamento dei flag, questa volta però esclusivamente in dipendenza dei Command esterni. Viene qui implementato un meccanismo per far sì che il Command di Start venga inoltrato non appena viene premuto il tasto, indipendentemente da quando questo viene rilasciato, ed esclusivamente nell’istante iniziale (cioè il comando viene inoltrato una sola volta per ogni pressione del tasto). Infatti si vorrebbe che la rispondenza tra la pressione del tasto e l’effettiva esecuzione del comando fosse come evidenziato nella seguente figura:

Figura 3: Specifica sul Command di Start

Il codice relativo è:

// Settaggio flags relativi ai comandi

asm(" ld Com_stop, a");

asm(" bc Not_stopping_writing, aneq"); // Se com_stop=1 non dò STOP asm(" ld #00h, a");

asm(" stl a, Flag_start_stop"); // Flag_start_stop=0 è STOP asm(" b Azzera_Out");

asm("Not_stopping_writing"); asm(" ld Com_start, a");

asm(" bc Not_starting_writing, aneq"); // Se com_start=1 nn dò START asm(" ld Com_start_mask, a");

asm(" bc Commands_Flags_Setted_wr, aeq"); // START già premuto asm(" ld #00, a");

(19)

asm(" stl a, Com_start_mask"); // Per avere START sulla pressione asm(" ld #01, a");

asm(" stl a, Flag_start_stop"); // Flag_start_stop=1 Vale START asm(" b Init");

asm("Not_starting_writing"); asm(" ld #01, a");

asm(" stl a, Com_start_mask");

asm("Commands_Flags_Setted_wr");

È importante notare che l’ordine con il quale vengono testati i flag impostati dai Command esterni non è casuale: si testa prima il Command Com_pause nella sezione “Test e aggiornamento dei flag prima della procedura”, poi il Command Com_stop e infine il Command Com_start nella sezione “Test e aggiornamento dei flag dopo la procedura”. Questo significa che durante la pressione del tasto Pause, altre eventuali pressioni (contemporanee) dei tasti Start o Stop, evidentemente accidentali, non provocano alcun effetto perché la fase che modifica i flag in base a questi comandi viene saltata in quanto se letto attivo il Command Pause si salta direttamente alla label “Azzera_Out” in fondo al codice. Per quanto riguarda il Command Com_stop invece, questo viene testato prima del Com_Start, e per tutta la permanenza di tale variabile al valore logico zero (che corrisponde al tempo nel quale viene premuto il tasto di Stop) si ha che il Flag_start_stop viene sempre posto a zero (fase di Stop) e si salta alla label “Azzera_Out”, come per il Pause. Questo accade indipendentemente dalla variabile Com_start, relativa allo Start, che non viene neanche testata finché è premuto lo Stop, per il fatto che viene saltata la procedura di testing. Ciò significa che se vengono premuti contemporaneamente i tasti Start e Stop, al rilascio di questi ultimi anche se viene rilasciato prima il tasto Stop, la macchina si troverà comunque in fase di Stop come nell’istante immediatamente successivo alla pressione di quest’ultimo. Si implementa tale meccanismo per evitare che possano avvenire cancellazioni non volute dei dati per aver magari sfiorato il tasto Start erroneamente quando si voleva premere Stop e quindi sono stati premuti entrambi i tasti.

Se dunque non viene premuto il tasto di Stop si arriva alla label “Not_stopping_writing” (siamo sempre in fase di scrittura) dove troviamo la sequenza di comandi che implementa il meccanismo presentato all’inizio del paragrafo. Il fulcro

(20)

del problema è quello di poter distinguere il primo istante nel quale viene premuto il tasto di Start dai successivi. Per far questo si è utilizzata una seconda variabile, chiamata Com_start_mask, che mantiene memoria del precedente valore assunto dalla variabile Com_start. Se Com_start viene letto a livello logico alto vuol dire che in quel momento non è premuto il tasto di Start e quindi non si va a modificare il Flag_start_stop perché comunque si rimane nello stato nel quale ci si trovava precedentemente. Se Com_start viene letto a livello logico basso allora significa che il pulsante di Start è tenuto premuto. A questo punto si testa la variabile Com_start_mask e si verifica che valga un 1 logico. Se è così significa che l’istante considerato nel quale si è verificato Com_start = = 0 è il primo istante che verifica tale condizione, cioè è il primo momento nel quale viene premuto il tasto di Start. È solo in questa condizione che Flag_start_stop viene messo ad uno logico e l’esecuzione del codice riparte dalla label “Init”, quella parte di codice che presenta le inizializzazzioni dei flag e dei puntatori messa subito prima del while( ). Se non si usasse la variabile Com_start_mask si opererebbe tutte le volte il salto a questa parte di codice con il risultato di rieseguire tutte le volte queste inizializzazioni. Per l’utente questo avrebbe l’effetto di far cominciare il processo stabilito (tramite l’impostazione dei Setting) solo una volta rilasciata la pressione dal tasto di Start, cosa non gradevole a nostro avviso. Se il pulsante di Start viene quindi premuto mentre è già in atto una registrazione si ottiene l’effetto di far ripartire da capo la registrazione, senza necessità di premere il pulsante di Stop tra le due successive pressioni del tasto Start.

Come già detto la parte relativa ai comandi nella lettura è identica e quindi non viene qui riportata.

Figura

Figura 1: GPIOCR
Figura 2: GPIOSR
Figura 3: Specifica sul Command di Start

Riferimenti

Documenti correlati

variabili di controllo del ciclo all'interno del corpo del ciclo stesso, vi rimane solo. corpo del ciclo stesso, vi rimane solo l’operazione vera e propria

Sulla pulsazione sempre uguale di un brano possiamo allora inserire note di diversa durata,che, ripetendosi in modo regolare, rendono la mia musica divertente e piacevole..

Riduzione dei rischi Riduzione delle violazioni alle norme di sicurezza Riduzione del numero di infortuni Riduzione delle fluttuazioni della produzione Riduzione delle turbative

SA 091 Quando si giunse al borgo del massacro nazista v. DGLI, uccello dal piumaggio scuro macchiettato di bianco e dal becco diritto e giallognolo.. DGLI, pesce d’acqua dolce

COLTIVAZIONI Coltiv. Altre coltivazioni Industriali. 26 Altre legumlnose da granella. 27 Legumi freschi da sgusciare. medio piante per ha. Semplici e ccn piante legno8e

PREVEDERE H >= 0,60 m CONDOTTA IDRICA!. FOGNA H>=0,60m L

"Nuovo Codice Della Strada"; essi dovranno essere realizzati con lamiere di alluminio e pellicola retroriflettente di classe 2, pali di sostegno

Il principale problema che deriva dal trattamento di spese in conto capitale (come quelle per R&S, formazione e pubblicità a sostegno del brand) come spese