You are on page 1of 15

Progetto di un a tastiera

“MIDI Master Keyboard”


Progetto e realizzazione di un dispositivo per il polling temporizzato di una matrice di contatti e la
generazione conseguente di messaggi secondo lo standard musicale MIDI.

Corso:

Elettronica III

Studente:

Giancarlo Todone
Introduzione

Lo scopo del progetto era quello di trovare un campo


di utilizzo reale per il microcontrollore Microchip
PIC18F452 che pur dimostrandone la potenza e la
flessibilità, non necessitasse di molta circuiteria
esterna e fosse di facile ed economica costruzione per
chiunque volesse riprodurre il dispositivo. Per
motivazioni contingenti è stato scelto di usare il PIC in
campo musicale, e precisamente per costruire una
cosiddetta “master keyboard” MIDI, o “tastiera muta”,
e cioè un dispositivo che analizzi lo stato di un’insieme
di tasti e resistenze variabili disposti a foggia di
tastiera musicale e generi a partire da esso un
adeguato flusso di dati MIDI con cui comandare un Figura 1 - prototipo del dispositivo di polling e generazione
sintetizzatore, un campionatore o un altro strumento messaggi MIDI
MIDI “slave”. Per l’hardware dei tasti musicali si è
riciclata una vecchia tastiera che –per quanto non professionale- dispone della forma e dei contatti
appropriati a gestire le caratteristiche richieste. Il protocollo MIDI -riassunto di seguito- dimostra una certa
complessità quando ci si trovi a doverlo interpretare (poiché per questioni tecniche è necessario
decodificare anche molti dati ai quali non si è direttamente interessati) ma si rivela abbastanza semplice nel
momento in cui si debbano invece generare comandi di un insieme ristretto di tipologie. Per il progetto si è
deciso di implementare i comandi MIDI note-on e note-off per segnalare la pressione dei vari tasti, di
leggere la “pitch-wheel” o “controllo del portamento”, di inoltrare comandi relativi al pedale del sustain e
gestire il cosiddetto “active-sensing”: è comunque facile aggiungere a richiesta fino ad altri 7 comandi
analogici e diversi altri comandi discreti (il numero è dipendente da eventuali tecniche di multiplazione). In
particolare, un punto focale dell’intero progetto è la gestione della “velocity” o “dinamica”, cioè della
rapidità -con cui solitamente si approssima la forza- con la quale ogni tasto viene attivato, parametro che di
conseguenza viene usato per comandare l’espressione di ogni singolo suono prodotto. Per poter gestire
tutti gli aspetti discussi finora –in particolar modo la dinamica- è stato necessario progettare del semplice
hardware dedicato, incarnato da due de-multiplexer 74hc138 economici (circa 0,60 euro l’uno) e di
semplice utilizzo, ed è stato inoltre necessario “spremere” abbastanza la potenza del PIC utilizzando un
quarzo da 20 MHz direttamente connesso col microcontrollore. Il resto dei componenti è passivo (tranne il
classico regolatore di tensione 78ls05) e rappresenta il tipico setup per un PIC: alimentazione, clock, reset.
Nel prototipo –perfettamente funzionante- realizzato su piastra millefori, mancano alcune raffinatezze
come resistenze limitatrici di corrente o condensatori di de-bounce, che sono però stati aggiunti nel
progetto CAD sviluppato con il software gratuito EAGLE: grazie ad esso è quindi possibile generare semi-
automaticamente anche una PCB dedicata al circuito, da incidere con i soliti metodi.

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 1


Materiali ed attrezzature

Il Microchip PIC18F452 è un microcontrollore a basso consumo


dotato di una CPU RISC capace di eseguire fino a 10 milioni di
istruzioni al secondo, di 1,5 Kbyte di ram on-chip, 256 bytes di
eeprom gestibile con istruzioni dedicate, memoria programma
di 16 K istruzioni e di diverse periferiche come timers, un
USART e un convertitore AD multiplato su 8 ingressi. Esso
risulta molto comodo per la compatibilità –ottenibile con sforzi
limitati- verso molti altri dispositivi della stessa casa di
produzione, ormai molto diffusi e largamente utilizzati.
Durante questa esperienza è stato quindi possibile riutilizzare il
Figura 2 – caratteristiche e pedinatura del know-how accumulato con altre periferiche simili, ed
PIC18F452
addirittura l’hardware di programmazione precedentemente
auto costruito.

L’altro integrato adottato nel progetto è il 74hc138, una semplice logica combinatoria
che implementa un de-multiplexer mantenendo alte o basse le diverse 8 uscite a
seconda della configurazione binaria presente su 3 ingressi e 3 linee di enable (in figura
pedinatura e tabella di verità). In particolare, quando abilitato, l’integrato –qui usato
nella sua versione invertente- pone a 0v una delle 8 linee di uscita normalmente a Vcc,
corrispondente al numero binario in ingresso sui tre input.

Figura 3 - pedinatura
dell'integrato
74hc138

Figura 4 - tabella di verità dell'integrato 74hc138, ripresa dal suo datasheet

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 2


Per questioni di comodità, e per permettere a chiunque
di costruire la sua versione del dispositivo, si sono usati
software gratuiti o versioni dimostrative gratuite di d
software commerciali. Per la programmazione
C/assembler, è stato adottato MikroC, un ambiente
semplice e rapido in cui si produce codice riutilizzabile
anche nel’ufficiale C18 di Microchip (con minime
modifiche); il software permette di creare e ridistribuire
ridistri
liberamente progetti, ma permette la compilazione di
Figura 5 - schema elettrico del programmatore JDM, qui fino a 2000 parole di istruzione, dopo le quali è
dimostrato per l'uso con un diverso modello di PIC necessario adottare la versione a pagamento (che costa
poco più di 100 euro). Nonostante l’ambiente MikroC
permetta l’interazione con vari hardware di programmazione/ICD, per questo progetto si è fatto uso del più
semplice ed economico programmatore JDM (in figura foto e schema elettrico), ricorrendo talvolta
all’uscita seriale hardware del PIC per le operazioni di debug. Il software di programmazione
programmazion gratuito
utilizzato è l’ottimo PicPGM che vanta notevoli funzioni di auto-detect
auto detect di programmatori e microcontrollori,
al quale sono stati dati in pasto direttamente i binari generati da MikroC. Per verificare la regolarità del
ciclo di polling sono stati usati un’oscilloscopio (non strettamente necessario) e un frequenzimetro auto
costruito (in figura). Una volta terminato e fatto funzionare il prototipo, si è proceduto al disegno CAD dello
schema elettrico con la versione dimostrativa gratuita di EAGLE, un software che permette di generare in
maniera assistita anche le PCB (nella versione dimostrativa limitate per dimensioni).

Figura 6 - foto di un
semplice
programmatore JDM
(autocostruito)
adattato a
funzionare con
packaging diversi

Figura 7 - utilizzo del frequenzimetro autocostruito


(con PIC16F84) per verificare la frequenza di polling di
circa 1 KHz

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 3


Lo schema elettrico

Per completezza, in primis riportiamo anche la


configurazione di base di un PIC. I condensatori C1
e C5 con il regolatore di tensione 78ls05
costituiscono una sorgente di tensione stabilizzata a
5 Vcc. Il valore del condensatore elettrolitico è
abbastanza elevato da garantire la continuità
dell’alimentazione anche durante un elevato
assorbimento da parte di un altro componente del
circuito o durante i possibili sbalzi nella tensione di
alimentazione non regolata (marcata 6-10v), ma
abbastanza basso da consentire un ridotto tempo di
start-up, che consente di polarizzare il piedino di
reset MCLR con una sola resistenza direttamente a
5Vcc, senza condensatori di temporizzazione
(solitamente si collega un condensatore tra MCLR e
GND per fare in modo che il PIC resti resettato
finchè l’alimentazione non si stabilizza). La base dei
tempi utilizza l’oscillatore interno (qui non facciamo
Figura 8 - configurazione di base del PIC: alimentazione, clock, uso di PLL) che si basa sul quarzo esterno -in questo
reset. caso da 20 MHz- stabilizzato dai due condensatori
da 15 pF.

Figura 9 - de-multiplexer
Figura 10 - de-
che gestisce i banchi multiplexer che gestisce
"before"; viene attivato
i banchi "after"; viene
quando RD3 è posto a attivato quando RD3 è
livello logico basso
posto a livello logico alto

Le linee RD0-RD2 del PIC sono connesse alle linee di ingresso di entrambi gli integrati 74hc138, mentre RD3
è collegata in modo da abilitare uno o l’altro integrato esclusivamente a seconda del suo livello logico;
questo in pratica ci consente di ottenere logicamente un unico de-multiplexer che accetta un numero
binario su 4 bit (quindi da 0 a 15) e pone a livello logico basso la linea corrispondente, lasciando a livello
alto tutte le altre. Per esempio, se RD0-RD3 vale 0, la sola linea “bank A” viene posta a 0v; se RD0-RD3 vale
1, la sola linea “bank B” viene posta a 0v; se RD0-RD3 vale 8, la sola linea “bank A’ ” viene posta a 0v.
Questo consente di effettuare la scansione delle note per banchi. Ognuno degli 8 banchi “A”, “B”, “C”, “D”,
“E”, “F”, “G”, “H” attiva un gruppo di otto note che vengono lette contemporaneamente dagli otto ingressi

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 4


RB0-RB7 del PIC. I corrispettivi banchi con l’apice servono per il rilevamento della dinamica; ogni nota
chiude in rapida sequenza due contatti: uno che potremmo chiamare “before” e successivamente un altro
che potremmo chiamare “after”. Da quanto ravvicinatamente i contatti “before” e “after” vengono chiusi,
dipende il parametro di dinamica di ogni pressione. Ad esempio, ponendo a 0 le linee RD0-RD3 attiviamo il
banco A e possiamo quindi leggere su RB0-RB7 lo stato degli switch ”before” delle prime 8 note della
tastiera; ponendo RD0-RD3 a 8 attiviamo il banco A’ e possiamo quindi leggere su RB0-RB7 lo stato degli
switch “after” delle prime 8 note. Abbiamo visto che “attivare” un banco significa porre la corrispondente
linea a 0 (stiamo quindi usando la logica negativa); ciò è dovuto a come è costruita la matrice di contatti (in
figura) e anche al fatto che in questo modo si possono sfruttare le resistenze di pull-up programmabili
interne della porta RB del PIC.

Figura 11 - costituzione della matrice di contatti della tastiera (semplificata a tre banchi da tre note per chiarezza). I diodi evitano
ritorni di corrente in caso di pressioni contemporanee e fungono inoltre da blande resistenze. Le resistenze di pull-up nel nostro
caso sono interne al microcontrollore.

Figura 12 - suddivisione della tastiera in banchi da 8 note. I banchi A, B, C,... permettono la lettura degli switch "before", mentre
A', B', C', ... permettono la lettura degli switch "after"

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 5


L’interfaccia MIDI è costituita da una semplice
resistenza connessa alla porta TX dell USART
integrato nel PIC. Come vedremo, infatti la
trasmissione MIDI è una trasmissione seriale su una
linea in “current-loop” per cui vengono fornite
anche le linee Vcc e Gnd. Lo standard MIDI prevede
l’utilizzo di un optoisolatore, ma esso è a carico del
Figura 13 - interfaccia MIDI. dispositivo “slave”, e quindi non dobbiamo
preoccuparcene.

Di seguito vengono riportate le pedinature dei connettori utilizzati per collegare la matrice di contatti (e
pochi altri dispositivi) alla scheda del prototipo. Quello a 20 contatti “grigio” era già presente ed è stato
mantenuto non modificato per consentire l’utilizzo della matrice con altri progetti precedentemente
sviluppati: trasporta le linee relative ai banchi A, B, C, D, E, F, G, H e due contatti del pedale del sustain;
quello a 16 contatti “colorato” –collegato ex novo- trasporta le linee dedicate ai banchi A’, B’, C’, D’, E’, F’,
G’, H’ e delle linee dedicate a controller analogici (resistenze variabili) che sono poi collegate alle linee AN
(il convertitore ADC) del PIC.

Figura 14 - connettore a 20 pin, Figura 15 - connettore a 16 pin, Figura 16 - collegamento della


osservato "da sotto" osservato "da sotto". PB = Pitch- resistenza variabile del Pitch-
Bender Bender (controllo del
portamento)

La resistenza variabile da usare come pitch-bender va


semplicemente collegata con PB al comune, Vcc su uno dei
piedini rimanenti e Gnd sull’altro. Data la natura economica
della tastiera, essa dispone però di una “rotella” per il
controllo del portamento che non si basa su resistenza
variabile ma su una matrice di contatti mostrata in figura. Si è Figura 17 - sulla destra la schematizzazione della
ovviato collegando i contatti con delle resistenze, in modo da PCB della rotella del portamento, sulla sinistra la
rete di resistenze per emulare un resistore
emulare sommariamente un resistore variabile “a gradoni”, e
variabile
smussando poi le letture con un filtro software sul micro.

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 6


Figura 18 - la rotella del controllo portamento disassemblata; la PCB a destra è autoesplicativa: il
trascinamento della rotella provoca la chiusura dei contatti in diversi modi.

Il protocollo MIDI

Il protocollo MIDI
rappresenta un ottimo
caso di studio perchè
abbastanza semplice da
essere comunque molto
comprensibile, ma
abbastanza complesso da
non risultare banale.
Inoltre, si tratta di una
comunicazione seriale Figura 19 - Connessione MIDI - lato ricevitore(slave); la resistenza di protezione
dell'optoisolatore è di 220Ω, mentre quella di pull-up di 1KΩ
asincrona -e in quanto
tale facilmente simulabile.
I dati viaggiano su una linea a bassa tensione con una tecnica chiamata "current loop" per interfacciarsi con
la quale lo standard MIDI prevede l'uso di optoisolatori come il comune 6N138 e l'adozione di un baud-rate
non standard di 31250 (+/- 1%).
La pubblicazione delle prime specifiche risale al 1983, ma
lo standard è sopravvissuto fino ad oggi (e continua ad
imporsi) nonostante le pecche che ovviamente comincia a
dimostrare. Difetti sensibili risiedono sia nella logica del
protocollo, sia nelle specifiche di comunicazione elettrica,
originariamente pensati per comunicare da un singolo
master ad un singolo slave in maniera unidirezionale, poi
adattati a gestire loopbacks e catene di strumenti ed
effetti musicali grazie anche all'introduzione del MIDI-
THRU, una porta che replica in uscita i messaggi arrivati
Figura 20 - Connessione MIDI - lato trasmettitore
(master); si noti il pin collegato direttamente a Vcc e il alla porta MIDI-IN dello stesso strumento. In questo modo
pin centrale (GND) che viene lasciato scollegato per -grazie anche alla suddivisione in canali virtuali di cui
evitare oscillazioni nel potenziale di massa; entrambe le parleremo- ogni strumento osserva l'intero flusso di dati
resistenze sono da 220Ω in ingresso, e filtra da esso quelli che è programmato per
recepire, passando poi i dati ad altri strumenti tramite la
porta THRU. Così facendo, però -non essendo tra l'altro il canale di comunicazione di banda molto larga e
non prevedendo il protocollo un sistema di rilevamento o correzione degli errori- si introducono effetti
indesiderati e latenze, cui si è cercato di ovviare migliorando nel tempo i dispositivi implementanti

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 7


piuttosto che lo standard. Per questi motivi, da sempre gli strumenti MIDI professionali hanno richieste di
latenza molto bassa e capacità di interpretare "elasticamente" il protocollo.

Le informazioni che si possono ricavare da uno stream di comandi MIDI sono organizzate in messaggi, che
sono composti di "opcodes" (o "status bytes") seguiti da dati. Esistono poi degli opcodes particolari
indicanti messaggi di sistema.
Osservando un qualsiasi dato in transito durante una comunicazione, è possibile dire immediatamente di
che tipo si tratta: infatti qualsiasi byte con il bit 7 impostato a '1' rappresenta un opcode, altrimenti -se '0'- i
sette bit meno significativi rappresentano un dato, come il parametro di qualche comando (quindi parlando
di byte di dati, in realtà d'ora in poi intenderemo i 7 bits utili rimasti). Per interpretare correttamente una
comunicazione, quindi, bisogna tener conto del tipo di byte che si sta osservando e dell'evoluzione della
comunicazione. In dettaglio, ecco le tipologie di messaggi:

opcode nome descrizione e numero di bytes di parametri


0x80-0x8f note off indica di silenziare una nota; è seguito da due byte di parametri (uno
per la nota, l'altro per l'intensità)
Status bytes relativi ad un canale virtuale

0x90-0x9f note on indica di suonare una nota (o silenziarla se l'intensità è 0)


0xa0-0xaf key pressure "after-touch"; è seguito da due byte di parametri (uno per la nota,
l'altro per la presenza di effetto)
0xb0-0xbf Cc parameter modifica di un parametro continuous controller; è seguito da due byte
(uno per il codice controller, l'altro per la nuova impostazione
parametro)
0xc0-0xcf Program change seleziona uno strumento; è seguito da un byte che indica il codice del
nuovo strumento da adottare
0xd0-0xdf chan. pressure effetto di pressione tasti che interessa l'intero canale (non
perfettamente specificato); è seguito da un byte indicante l'intensità di
effetto
0xe0-0xef pitch wheel indica la posizione assoluta della rotella che sposta finemente il tono; è
seguita da due bytes rappresentanti una parola di 14 bits (i 7 bits meno
significativi per primi)
0xf0 system indica l'inizio di un messaggio di sistema seguito da un numero variabile
System Messages, al di fuori della logica dei

exclusive di bytes di parametri (va terminato con un EOX)


0xf1 undefined
0xf2 song position per i sequencers; indica la nuova posizione in una traccia; seguito da 2
bytes che costituiscono il valore di 14 bits indicante la posizione, i 7
meno significativi per primi
canali virtuali

0xf3 song select per i sequencers; indica il codice della nuova traccia; è seguito da un
byte indicante il codice della nuova traccia
0xf4 undefined
0xf5 undefined
0xf6 tune request per i sintetizzatori analogici: indica la richiesta di risintonizzare gli
oscillatori. Non è seguito da alcun dato
0xf7 EOX indicatore che termina una sequenza di parametri in un messaggio di
(terminator) sistema a lunghezza variabile; anche altri messaggi come note-on o
note-off possono interrompere una sequenza. Non è seguito da alcun
dato.
0xf8 timing clock usato per sincronizzare le macchine (specialmente le “drum-machines”)
0xf9 undefined
Realtime Messages

0xfa start per sequencers: indica di iniziare la riproduzione


0xfb continue per sequencers: indica di continuare la riproduzione
0xfc stop per sequencers: indica di fermare la riproduzione
0xfd undefined
0xfe active sensing viene mandato ogni 300 ms circa dal master quando questo non ha
niente da fare (per far capire che è ancora vivo); quando non viene
ricevuto alcun messaggio per più di 300 ms il master è da considerarsi

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 8


opcode nome descrizione e numero di bytes di parametri
disconnesso
0xff system reset reset di sistema

alcune precisazioni:
1. vale la regola del "running status byte": una volta che un messaggio viene ricevuto, non occorre
ripetere l'opcode prima di mandare i dati successivi, se questo non cambia (vedere esempi in
seguito)
2. una note-on con intensità posta a 0 è interpretata come un note-off; questo, insieme alla
convenzione del "running status byte" permette di inviare lunghe stringhe di eventi note-on/note-
off rapidamente
3. MIDI prevede la suddivisione in canali virtuali; i messaggi da 0x80 a 0xef sono raggruppati in gruppi
di 16: nel messaggio (nei 4 bits meno significativi) è insito il canale virtuale al quale ci si riferisce; ad
esempio 0x90 significa "note-on sul canale 0", mentre 0x91 vuol dire "note-on sul canale 1" e così
via
4. i messaggi "undefined" vanno semplicemente ignorati
5. gli ultimi 8 messaggi da 0xf8 a 0xff chiamati "realtime messages" (è più in generale i messaggi senza
parametri in coda) così come altri System Messages possono venire inframezzati ad altri comandi
ed è quindi necessario gestirli -in ricezione- anche se non interessa l'informazione veicolata
6. i messaggi "cc parameter" da 0xb0 a 0xbf indicano i valori di eventuali controllers (continui o
discreti) come manopole o sliders che possono venire associati ad effetti: solo il contoller continuo
di codice 0 è standardizzato ed è la cosiddetta "modulation wheel"; tutti gli altri codici di parametro
controller sono proprietari e tendenzialmente diversi da macchina a macchina. I messaggi
parameter possono contenere ulteriori comandi valevoli per l'intero canale al quale si riferiscono
(aggiunti con questo trucco a quelli già esistenti):

codice Nome secondo byte di parametro


controller
0x00 Bank select il banco strumenti da selezionare (0 per “General MIDI”)
Controllers veri

0x01 Modulation la nuova impostazione di modulazione


standard o
e propri,

quasi

Wheel
0x07 Volume l’intensità di volume da impostare
0x40 Sustain 0 per pedale sustain non premuto, 127 per pedale premuto, indefinito
per qualsiasi altro valore (da ignorare)
0x7a local control 0 = local control off, 0x7f = on
indica ad esempio se una tastiera deve suonare gli eventi locali o quelli
Controllers fittizi, usati come

inviati da remoto
comandi aggiuntivi

0x7b all notes off 0


0x7c omni mode 0
off
0x7d omni mode 0
on
0x7e monophonic numero di canali monofonici o 0 per indicare un numero pari ai
mode riceventi
0x7f polyphonic 0
mode

in più, oltre al controller 0x7b, anche quelli da 0x7c a 0x7f silenziano ogni nota.

7. per semplicità di discorso, chiameremo "comandi" gli opcodes riferiti ad un canale (da 0x80 a 0xef),
"System Messages" (o SM) quelli da 0xf0 a 0xff e "dati" tutti gli altri valori

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 9


Analizziamo per esempio la seguente sequenza:
0x91 0x40 0x41

• 0x91 significa "Note-on sul canale 1"


• 0x40 = la nota da "accendere" è la numero 64 (il DO centrale delle tastiere)
• 0x41 = la "velocity" (assimilabile con l'intensità con cui suonare la nota)

Vediamo ora un'altra sequenza:


0x91 0x40 0x41 0x4c 0x30 0x40 0x00

• i primi tre bytes hanno lo stesso significato che nel precedente esempio: suonare il DO centrale a
un'intensità media
• il quarto byte è ancora un dato, quindi vale l'ultimo status byte ricevuto, ovvero 0x91; i byte 4 e 5
vogliono quindi dire "suona il DO un'ottava sopra il DO centrale a un'intensità lieve sul canale 1"
• i bytes sei e sette sono ancora dati, quindi vale ancora lo status byte 0x91 (note-on sul canale 1);
l'intensità però stavolta è 0, quindi bisogna interpretare il messaggio come "spegni
immediatamente il DO centrale"

Ed ecco un ultimo esempio di sequenza valida:


0x91 0x40 0xfe 0x41 0x4c 0x30 0xf0 0x01 0x02 0x03 0xf7 0x40 0x00

• La sequenza di eventi relativi ai canali è identica a prima, ma la sequenza è stata inframezzata da


messaggi di sistema (un "realtime message" e un "system exclusive")
• i dati inframezzati alla sequenza originale sono
o 0xfe = realtime message chiamato "active sensing" (qui non ha molto senso, ma serve a
fabbricare l'esempio)
o 0xf0 0x01 0x02 0x03 0xf7 = sequenza "system exclusive" a lunghezza variabile che trasporta
in questo caso il payload 0x01 0x02 0x03 (anche qui i dati inseriti sono a puro titolo
d'esempio)
• Si noti che il realtime message è inserito addirittura tra il primo e il secondo parametro del primo
comando "note-on".

Il software

Si è optato per un loop while infinito, nel quale ad ogni ciclo viene effettuata una lettura completa di tutti i
dispositivi: tutti i banchi di note “before”, tutti i banchi di note “after”, ingressi discreti (pedale) e analogici
(pitch-wheel).

while (1)
{
scanBeforeAndAfter();
readOtherInputs();
sendMIDIMessageAccordingly();
handleActiveSensing();
}

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 10


In un sottociclo, una variabile viene incrementata da 0 a 15 e riportata in output sui primi bits della porta
RD; ad ogni sottociclo, sugli otto ingressi di RB si leggono (invertendoli) i bit corrispondenti allo stato delle
otto note del banco selezionato. Tenendo traccia dei vecchi valori è possibile sapere quali switch sono
appena stati premuti o rilasciati:

void scanBeforeAndAfter()
{
for (i = 0; I < 16; ++i )
{
oldData[i] =newData[i]; // each bit contains on/off status of a switch;
newData[i] = ~PORTB; // 1 byte = 1 bank = 8 switches
justPressed[i] = ~ oldData[i] & newData[i];
justReleased[i] = oldData[i] & ~ newData[i];
}
}

L’algoritmo per il rilevamento della dinamica è semplice: vi sono 64 possibili note, e di conseguenza 64
misure dei tempi tra “before” e “after”; dunque sono allocati nella ram interna 64 bytes ognuno dei quali
memorizza il valore della velocity della nota corrispondente. Ogni valore di velocity viene inizializzato a 127
(massima velocity nello standard MIDI). Ad ogni ciclo, se lo switch “before” di una nota risulta chiuso, allora
decrementiamo la corrispondente velocity; se lo switch “after” è appena stato premuto, allora procediamo
a spedire un messaggio MIDI di note-on in cui la velocity è quella memorizzata; se lo switch “before” è
appena stato rilasciato, provvediamo a fabbricare e inviare un messaggio MIDI note-off e resettiamo la
corrispondente velocity a 127.

for (i = 0; i < 64; ++i)


{
if (pressedBefore[i]) // for sake of simplicity here we omit the code that translates index
--velocity[i]; // from bit mask to linear array

If (justPressedAfter[i])
sendNoteOn(i, velocity[i]);

if (justReleasedBefore[i])
{
sendNoteOff(i);
velocity[i] = 127;
}
}

Il precedentemente menzionato algoritmo di smussamento dei valori del pitch-bender viene implementato
come un controllore PID elementare in cui la parte integrativa sia posta a 0.

filteredValue = filteredValue + (value - filteredValue)*k, 0<k<1 (in questi casi solitamente piccolo)

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 11


Ovviamente per evitare fenomeni di accumulo dell’errore e aliasing sarebbe necessario usare dei numeri
reali; inoltre è necessario adattare le diverse dimensioni in bit: si è deciso di implementare questa funzione
con la tecnica fixed-point. L’ADC del PIC fornisce un numero intero non segnato a 10 bits, mentre il
protocollo MIDI richiede per il parametro del pitch-bender un numero intero non segnato a 14 bits,
entrambi ovviamente gestiti poi con interi non segnati a 16 bits che lasciano quindi spazio ad almeno 2 bits
per la parte frazionaria.

La lettura dello stato del pedale viene effettuata direttamente su uno degli ingressi digitali della porta C del
PIC (attualmente senza multiplazione): un meccanismo logico permette di gestire pedali dai contatti sia
normalmente aperti che normalmente chiusi (una lettura effettuata allo start-up prima di entrare nel ciclo
principale stabilisce la norma)

Come spiegato in precedenza, parte dei meccanismi del protocollo MIDI sono dedicati alla minimizzazione
del traffico di dati. La già descritta convenzione del “running status byte” prevede di evitare di reinviare due
comandi uguali che siano inframezzati solo da dati. A questo proposito, si è adottato un semplice
meccanismo che ricorda l’ultimo status byte inviato:

void sendCommand(cmd)
{
if (lastSB != cmd)
{
lastSB = cmd;
send(cmd);
}

activeSensingTimeout = 0
}

Nell’ultima riga si può notare l’azzeramento di una variabile che (contando semplicemente il numero di
cicli) permette di stabilire se è il caso o meno di inviare un “active-sense”, utile a segnalare la presenza e il
funzionamento del dispositivo quando non ci sono altri comandi da inviare per un certo tempo. Come
ultima operazione del nostro ciclo principale, infatti abbiamo:

++ activesensingTimeout;
if (activeSensingTimeout>300)
{
activesensingTimeout = 0;
send(activeSensingToken);
}

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 12


Conclusioni e possibili sviluppi

Collegando il dispositivo a degli analizzatori di protocollo MIDI (come per esempio un semplice terminale
che supporti il baudrate MIDI, o il progetto “FPGA_MIDI” sviluppato per il corso di elettronica II su board
Altera) si è proceduto a verificare che i messaggi vengono inviati correttamente.

Il dispositivo si comporta bene anche nelle prove pratiche, nelle quali si procede semplicemente a suonare
la tastiera e a far attenzione alle eventuali inesattezze di riproduzione del suono, come ritardi o veri e
propri errori. Per completare tale prova si è provveduto a collegare il circuito alla porta MIDI standard di un
PC (nel nostro caso tramite una scheda sonora Creative Sound Blaster Audigy Platinum) e ad eseguire un
semplice programma che traduca messaggi MIDI in suoni. Le latenze non sono avvertibili anche in casi
critici per il protocollo, come quello di molte pressioni simultanee e la risposta appare immediata,
dimostrando la semi-professionalità del dispositivo costruito; nonostante ciò, la pulsione al miglioramento
ci suggerisce eventuali modifiche apportabili al progetto. Una delle prime migliorie possibili sarebbe quella
di aumentare la velocità con la quale le scansioni si succedono: una prima idea potrebbe essere –date le
attuali ridotte dimensioni del codice eseguibile- quella di usare la tecnica dei loops “srotolati”. Il PIC 18F452
riesce a sostenere clock fino a 40 MHz, che sarebbe il doppio di quello attualmente in uso: ciò
permetterebbe di ravvicinare ulteriormente tra loro le scansioni e quindi migliorare la risposta della
dinamica. A tal proposito, la risposta dinamica del circuito è attualmente lineare, mentre è facile intuire che
allo scopo di simulare la forza di pressione, la velocity andrebbe distorta prima dell’invio, tramite -ad
esempio- una look-up table. La rotella del portamento andrebbe modificata in modo da azionare
direttamente un potenziometro, permettendo così di eliminare dal software il filtro, che è abbastanza time-
consuming. Al circuito andrebbero aggiunti pochi componenti passivi come resistenze limitatrici e un
condensatore di anti-bounce al fine di ridurre i –già minimi- consumi e garantire l’affidabilità. L’unico errore
non gestito del dispositivo, al momento, riguarda l’operatività in condizioni di alimentazione insufficiente
(es: batteria scarica): invece di smettere semplicemente di funzionare, il circuito comincia a commettere
errori di scansione, inviando messaggi pseudo-casuali. La cosa è eventualmente ovviabile con un minimo di
circuiteria esterna. Un ultima raffinatezza potrebbe essere quella di misurare la dimensione -in numero di
istruzioni- di ogni blocco condizionale, in modo da riempire di un numero adeguato di NOP uno dei due
rami di ogni istruzione condizionale, per fare in modo da avere cicli di tempo di esecuzione sempre
esattamente identico a se stesso (adesso sono presenti minime oscillazioni). Lo sviluppo di una board
dedicata permetterebbe di effettuare tests più seri ed eventualmente portare ad una produzione su medio-
piccola scala.

NB: progetti, schemi, immagini, foto, informazioni e codici sorgenti di Giancarlo Todone vengono rilasciati
con licenza Apache 2.0, a parte le informazioni sul protocollo MIDI 1.1 dedotte dall’ottimo documento “The
Usenet MIDI Primer” di Bob McQueer, facilmente reperibile in rete.

Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 13


Giancarlo Todone - Progetto e realizzazione di un controller master MIDI Pagina 14

You might also like