Scatola Musicale - Codice sorgente

Passiamo ora al programma da inserire nel microcontrollore: non descriverò i singoli step ora (se necessario vi saranno i commenti nel sorgente) ma dirò a grandi linee in che modo procede:

Innanzitutto il software è stato scritto in C nell’ambiente mikroCversione 8.2.0.0; La configuration word è 0x2109, impostata attraverso la voce di menù "Project –> Edit Project" Con le impostazioni che vedete nella figura:

Ovviamente va selezionato il microcontrollore 16F628A e la frequenza di clock appropriata (nel mio caso era 4 MHz, ma ciò è irrilevante poichè il compilatore eseguirà automaticamente gli eventuali calcoli necessari variando la frequenza di clock).

Il funzionamento del software è il seguente: innanzitutto si procede all’inizializzazione del modulo audio secondo le tempistiche specificate nel datasheet; poi si recupera dalla eeprom il volume da impostare (il modulo audio permette di impostare il volume attraverso un apposito comando) in modo da non doverlo impostare tutte le volte al livello desiderato. Il volume si cambia premendo due tasti appositi, ma vedremo dopo.

Dopo aver inizializzato il tutto parte il ciclo principale del programma: si legge ciclicamente la tastiera attivando una colonna alla volta e leggendo gli ingressi; per ogni tasto premuto, alla variabile "code" viene aggiunto un numero pari al doppio del numero del tasto precedente: il tasto 1 aggiunge 1 alla variabile se premuto, il tasto 2 aggiunge 2, il tasto 3 aggiunge 4, il tasto 4 aggiunge 8 ecc.

Una volta letta la tastiera, se la variabile “code” è diversa da zero significa che un tasto (o più) è stato premuto; si va quindi a controllare se è stato premuto uno dei due tasti per alzare o abbassare il volume e si agisce di conseguenza. Il volume modificato viene salvato nella eeprom.

Una volta controllato se bisogna modificare il volume, si chiama la procedura "uart_send_play" che prende come argomento la variabile “code” e ordina al modulo di riprodurre un suono; essa funziona in questo modo:

  • si converte la variabile passata come argomento in stringa attraverso la funzione IntToStr, già definita nell’ambiente mikroC che segue una particolare formattazione: restituisce una stringa di 6 numeri allineati a destra, i restanti caratteri a sinistra vengono riempiti con degli spazi.
  • si imposta il volume al livello desiderato dall’utente attraverso la procedura set_volume
  • si invia al modulo la sequenza per il comando Play: 0x10 per dire che il comando è play, 0x00 e 0x0A per dirgli che dovrà ricevere 10 byte per il nome del file: sono 10 perchè chiameremo i file da programmare sul modulo audio in un modo particolare: ad esempio il suono associato al pulsante 4, quindi codice 8 (vedi codice sorgente), è chiamato “000008.wav”; il suono associato al codice 256 sarà chiamato “000256.wav”; in questo modo la lunghezza del nome del file è sempre la stessa e il software si semplifica notevolmente
  • ora si invia al modulo il nome del file in questo modo: con un ciclo consideriamo singolarmente ogni carattere della stringa convertita dalla funzione IntToStr: se è uno spazio, si invia al modulo il carattere ‘0’, altrimenti si invia al modulo il carattere così com’è. Poi si invia al modulo la sequenza di caratteri per completare l’estensione, ossia ‘.’ ‘w’ ‘a’ ‘v’.
  • ora il modulo inizia la riproduzione del file audio, con un while aspettiamo che il pin BUSY torni alto ad indicare che ha finito, ma mentre aspettiamo ciò, controlliamo se l’utente preme il pulsante di stop, attivando la colonna e leggendo la riga corrispondenti al tasto STOP. Se il tasto è premuto, inviamo il comando di STOP.

La funzione uart_send_play è piuttosto intricata, ma non è per masochismo: chiamando i file da programmare sul modulo nel modo giusto e seguendo questa procedura per l’invio del comando, si permette di snellire notevolmente il codice: la funzione così ha solo bisogno di un numero che provvederà a trasformare nel giusto comando da inviare al modulo. Definire manualmente tutti i nomi dei file, ad esempio “ciao.wav” o “suono.wav” avrebbe comportato un aumento di memoria occupata non indifferente per un microcontrollore che di certo non abbonda e un appesantimento del codice.


Ecco il sorgente:codice sorgente

E l'hex già compilato:hex compilato

 


Vi chiederete perchè non ho assegnato semplicemente i numeri in modo crescente per ogni tasto: perchè nel caso si desiderino inserire dei suoni riproducibili con una combinazione di tasti, in questo modo si può fare; ad esempio, se desideriamo che si attivi un particolare suono alla pressione dei tasti 2 e 5, basta programmare sul modulo un suono chiamato “000018.wav” (2 + 16).

Non avrei potuto fare la stessa cosa se avessi assegnato semplicemente numeri crescenti, perchè la pressione del tasto 2 e del tasto 5 avrebbe dato come risultato il codice 7, numero che sarebbe stato già impegnato per il pulsante numero 7.

Se si desidera questa funzionalità bisogna però apportare una piccola modifica al codice aggiungendo, subito dopo il while (1) che determina l’inizio del ciclo iniziale, la seguente porzione di codice:

asm {
    controllo:
    movlw 0x1C
    iorwf porta,f
    movlw 0xF0
    andwf portb,w
    btfss status,z
    goto controllo
    movlw 0xE3
    andwf porta,f
}
Delay_ms(200);

per un semplice motivo: facciamo finta che l’utente voglia associare un suono ai tasti 2 e 5, come dicevamo prima: se questo pezzo di codice non ci fosse, l’utente premerebbe uno dei due tasti prima (perchè nessun essere umano riesce a premere due tasti insieme con precisione al microsecondo) e di conseguenza il microcontrollore riprodurrebbe subito il suono associato al tasto premuto prima.

Inserendo questo pezzo di codice, il microcontrollore attiva tutte le colonne e legge tutti gli ingressi, in modo da accorgersi se un qualsiasi pulsante è premuto. Quando si accorge che un qualsiasi pulsante è stato premuto, esce dal ciclo di controllo (quello che inizia con la label denominata appunto “controllo”), aspetta un po’ di tempo per permettere all’utente di premere tutti e due i tasti, e poi passa alla scansione della tastiera come detto in precedenza. Questo concede all’utente un certo lasso di tempo per premere tutti i pulsanti desiderati.