2020/05/30

Schema e codice del sintetizzatore

Lo schema quasi completo del sintetizzatore su breadboard è più o meno questo:

Si vedono la matrice (già mostrata), un array resistivo che è parte del circuito della matrice (due array in parallelo, in realtà, sicuramente perché non ne aveva uno del valore che gli serviva1), il µC 328P, il 4051, l’oscillatore, i futuri potenziometri, per ora trimmer (ADSR + LFO2), un condensatore di disaccoppiamento. Ci sono altri componenti passivi sulla breadboard (condensatori, principalmente, e resistenze, tre LED ma legati all’ISP), ma ancora devo trascriverli.

Avevo già mostrato lo schema del cuore del sintetizzatore in un altro post, ma ho corretto almeno un errore.

NOTA: poiché l’immagine del circuito sta su Google Drive ed è l’SVG esportato da KiCAD e Google Drive permette di aggiornare lo stesso file (aggiungere una nuova versione), se dovessi trovare altri errori o completarlo, nel post vedrete questi aggiornamenti. Questi eventuali aggiornamenti comunque non dovrebbero rendere obsoleto quanto già scritto.

Adesso voglio trovare nel codice dove imposta PB3, PB4 e PB5 per leggere i sei potenziometri attaccati al 4051 — quando non c’era, immmagino che i potenziometri andassero ad occupare altri bit della porta C; per questo magari inizialmente il numero di potenziometri era anche inferiore — addirittura io ne ricordo solo uno (quindi i valori venivano solo dai preset e non era possibile variarli se non ricaricando l’EEPROM con i nuovi preset).

Nello schema, sempre che non sia un mio errore di trascrizione, c’è una resistenza pull up; il valore che ho messo è 2.2k — non so perché, ma ho l’idea che sia più logico che sia 22k (poi ricontrollo). O forse non ha la funzione di pull up (?) ma serve per dare un offset alla tensione? O per limitare la corrente su quel pin? Possibile? Non lo so: ho buttato delle idee a caso 😄 ma non ho ancora chiaro se tali idee hanno un senso o no!

Il codice per PB3, PB4, PB5…

Ma quale versione andava bene per lo schema della breadboard?3 Cioè, la breadboard, quale schema ha? Come già detto non ho trovato nessuna corrispondenza. In compenso negli schemi c’è indicata la versione del codice con cui funziona, e nel codice la versione dello schema…

La I_7 ha solo un waves.h, ma tutte le altre tabelle e strutture sono nell’unico file mysynth-I_7.ino. Nella versione I_8 aveva scorporato le tabelle e le macro in tables.h e x_macro.h: sembra che stesse iniziando a fare ordine nel codice (e riscrivere alcune parti direttamente in assembly4). L’ultima versione del codice dovrebbe essere la O_0, stando alla progressione alfabetica; però in questa versione, se è pur vero che il .ino è stato toccato il 28 febbraio 2020 e uno dei .h il 18 gennaio (date fornite dal filesystem), gli altri file hanno data addirittura del 2019.

Non so cosa ci sia adesso nel 328P sulla breadboard. Nello schema D c’è scritto Con mysinth-I_1; il codice serie I versione 1 esiste solo archiviato in un .7z. Nello stesso archivio la versione 6 della serie I compare due volte, una volta con il suffisso _OK e un’altra volta senza (e quindi non funziona? e con quale schema?)

Nel codice serie I versione 8 si legge

con ISIS mysynth-8

e nello schema 8 c’è scritto che funziona con diverse versioni della serie I, tra cui anche I_8. Lo schema D ha i due 4051 e un solo 74HC273 (Octal D-type flip-flop with reset; positive-edge trigger).

Nella funzione di scansione dei potenziomentri quello che scandisce dipende da una variabile (PresetOn). È scritto che nel caso di preset attivi la scansione dei potenziometri non viene fatta (valgono i valori impostati da un preset). Era possibile richiamare dei preset ma anche memorizzarne (alcuni); a memoria mi sembra di aver letto di una funzione di sblocco dei potenziometri; quindi forse è necessario “sbloccarli”, giocare con i potenziometri a piacere, e poi salvarne i valori in uno degli spazi di memorizzazione dei preset.

In un if con commento legge pot ADSR si parte dalla maschera 01000111 in cui si fanno variare i tre bit a 0 in mezzo (in un loop da 0 a 7), quindi si va da 01000111 a 01111111. La maschera viene “sparata” su PORTB. Supponendo che PB0 sia il bit meno significativo, si deduce che quei tre bit che variano sono proprio PB3-5. Dopo aver impostato PORTB al valore della maschera aspetta 10 cicli e poi inizia l’ADC e legge il valore (mette ADSC alto nel registro ADCSRA, aspetta (busy wait) che torni basso, e a quel punto il valore della conversione è pronto e viene letto da ADCH5. Il valore letto viene diviso per una potenza di due che dipende dal potenziometro in questione (per i 2 ADSR, per i quali vanno letti 4 valori a testa, divide per 2, 1, 8 e 1): probabilmente valori determinati dal range di valori desiderato per quel particolare parametro dell’ADSR, e non da aggiustamenti empirici.

Si vede anche che PB0-2 sono messi alti; nella mia trascrizione PB0 non sembra connesso, mentre PB1-2 ancora devo vedere dove vanno. Nello schema D, del resto, non mi è affatto chiaro a cosa servono. Sono connessi ad un circuito fatto di condensatori e resistenze — pensavo che fosse un filtro e che quindi potessero essere le uscite audio. Ma allora… è stereo? E se fossero le uscite audio6, avrebbe senso metterle alte fisse nella scansione dei potenziometri? Forse sì? C’è un interrupt che li “corregge”? Tutto da scoprire e capire.7

Un’altra cosa da notare nella maschera è che PB7 è basso nella lettura dei pot ADSR e alto nella lettura pot MOD (che va da 0 a 4 soltanto, secondo loop da 1x000xxx a 1x100xxx ): il PB7 non è connesso nella breadboard, ma nello schema D va al INH (inhibit) dei 4051 (c’è un inverter realizzato tramite un transistor in modo che quando è INH uno non è INH l’altro e viceversa). Essendoci solo un 4051, questo non è mai inibito e una di quelle due letture non avviene mai8 o, se avviene, legge esattamente gli stessi potenziometri (che sono 6 invece di 8 sulla breadboard).9

Dopo queste due (eventuali) letture, legge sempre gli ultimi 3 pot (–Pitch) facendo un terzo loop da 1x101xxx a 1x111xxx.

E così è per i PB3-5: il codice che c’è sul 328P della breadboard potrebbe benissimo essere (e quasi certamente è) uno di quelli che sfruttano i due 4051 per leggere fino a 16 potenziometri.

E per quanto riguarda i LED?

Nello schema D, che penso sia il riferimento migliore per la breadboard, ci sono due 74HC273; uno degli scopi è proprio “agganciare” i valori per i LED. Nel codice (serie I, versione 8)

status_LED settato in sub ScanKeyBoard, dopo scanning tasti.

Ci sono anche delle define apposite:

#define LED_POTOFF
#define LED_ADSR1               0b11111110 // LED rosso ADSR1
#define LED_ADSR2               0b11111101 // LED rosso ADSR2
#define LED_ADSRACT             0b11111011 // LED verde attivazione pot ADSR
#define LED_MODOSC              0b11110111 // LED rosso modulazione freq LFO1
#define LED_MODEFX              0b11101111 // LED rosso modulazione chorus, vibrato LFO2
#define LED_MODACT              0b11011111 // LED verde attivazione pot EFX
#define LED_PERC                0b10111111 // LED percussione
#define LED_SPLIT               0b01111111 // LED split ?

e in effetti nella funzione di scansione della tastiera, dopo i commenti latch LED e usa fronte salita di ultimo pin colonna tastiera (rimasto basso dopo scanner), inizia il codice per “latchare” i LED:

  • DDRD0b11111111 8 bit PORTD output
  • attesa 5 cicli
  • PORTDstatus_LED
  • attesa 5 cicli
  • PORTCPORTC or 0b00011111 alza pin (PC4 era rimasto 0 dalla scansione)
  • DDRD ← 0 rimette 8 bit PORTD input
  • PORTD0xFF pullup

Nel prototipo su BB non succede niente, come si può immaginare: i pin della porta D diventano output e vengono valorizzati, ma non c’è nessuno “interessato”, ecc.

Il PC4 era rimasto 0 dalla scansione si riferisce al fatto che ha appena finito la scansione della tastiera, fatta mettendo di volta in volta a 1 tutti i bit della porta C tranne quello interessato, che nel ciclo va dal primo al quinto, sicché all’uscita dal ciclo a PORTC è stato assegnato per ultimo 0b11101111: proprio PC4 è basso. Quindi assegnando 0b00011111, lo riporta alto (e abbassa PC7, PC6 e PC5…?); e sul fronte di salita di PC4…

Che dovrebbe succedere?

Nello schema D, CLK sta su PB0. Non mi sembra che la porta C venga usata per altro oltre alla tastiera! Questo è il codice serie I, versione 8, come detto… Ma sullo schema D c’è scritto che va sì con la serie I, ma c’è solo la versione 1! Ho guardato il codice sbagliato per lo schema, o lo schema sbagliato per il codice.

Forse per il prototipo su BB è indifferente (tanto in ogni caso c’è solo un 4051), ma mi piacerebbe sapere con esattezza che codice c’è. Cercando uno schema che dica di andare con la serie I, versione 8… c’è lo schema 8 — per qualche motivo ero finito a guardare lo schema D, invece! Ho fatto un po’ di confusione. Comunque, nello schema 8 il CLK del 74HC273 in effetti va sul PC4.10

Per questo post può bastare: il letto chiama. Nei prossimi riprendo questa analisi del codice, non perché voglio deviare su un terreno a me più familiare, ma perché dall’analisi del codice, schema alla mano, verifico che quello che ho intuito finora del circuito sia corretto e torni con il codice. Il punto di incontro software-hardware… finalmente! 😄


  1. Ancora non ho letto il valore delle resistenze dell’array: non sono riuscito ad avere una buona visuale sulla stampigliatura; per averla devo staccare qualcosa e per ora non voglio “rischiare” tanto. Noti i valori R1 e R2, la resistenza usata per ciascuna “linea” sarà data dall’inverso di $\frac{R_1 + R_2}{R_1 R_2}$ — fin qui ci arrivo, grazie ai rudimenti ricevuti in un laboratorio di fisica…↩︎

  2. Per un totale di sei. Del settimo che si vede sulla breadboard in realtà sono usati solo due terminali, quindi è più un reostato o qualcosa del genere, e non è un parametro del sintetizzatore. Sarà usato per regolare qualche altra cosa, ma ancora non mi è chiaro.↩︎

  3. Sicuramente scarto *644_O: a quanto sembra aveva anche preso in considerazione l’idea di usare un ATmega un po’ più “capace”: il 328 forse andava strettino col codice e con le tabelle, e con le performance pure, credo. (Ricordo gli spernacchi caratteristici quando i dati non sono pronti per l’interrupt che deve “suonarli”). A giudicare dalla data, il .ino è stato toccato l’ultima volta il 10 marzo.↩︎

  4. Per maggiore compattezza, per provare a spremere ancora di più qualche ciclo…↩︎

  5. Ancora non sono andato a guardare i dettagli di come si fa sul 328. Al volo ho trovato questo document, che conferma i miei sospetti che quell’H in ADCH implichi l’esistenza di un ADCL dove vengon messi i bit meno significativi della conversione. Quindi deduco che papà non abbia usato la conversione a 10 bit, altrimenti vorrebbe dire che il codice legge solo 2 bit dell’intera conversione.↩︎

  6. La tecnica di produzione del suono è basata sulla PWM.↩︎

  7. Non credo che mio padre sia partito da zero: questi dettagli è probabile che vengano dal progetto già citato in almeno un precedente post. Lo scopo di queste pagine non è di scartabellare la rete alla ricerca delle fonti e citarle sempre accuratamente. Mi perdoneranno gli autori di tale fonti… magari quando sentirò la materia più mia, potrò dedicare più tempo anche alla corretta attribuzione. Ma per ora le uniche ricerche che faccio sono mirate a capire — se mi sembrerà di aver trovato una fonte, cercherò di ricordarmi di citarla. Comunque nel codice si legge primo loop da 0x000xxx a 0x111xxx. I bit che non interessano li mette a 1.↩︎

  8. Se viene fatta o meno dipende da una variabile, Preset_on.↩︎

  9. Il principio di funzionamento è lo stesso: una volta che funziona per due, funziona per otto. Nel trasferimento dalla breadboard a basetta sicuramente sarebbero stati aggiunti anche questi potenziometri, e pure tutto il resto necessario per leggere gli altri 8 e per accendere i LED, ecc. Il codice era pronto, gli schemi ci sono, la breadboard (prototipo) no, è più limitata.↩︎

  10. Il resto è simile e quindi torna. Forse ho perso un po’ di tempo a guardare lo schema sbagliato per il codice — o viceversa. Si capisce pure che sto facendo queste analisi mentre scrivo (e viceversa!): forse non il modo ideale di procedere. Anche perché è noioso per il lettore, e per niente utile per chi è interessato alla materia, camminare insieme a me in questa esplorazione. Ma questo blog non nasce con nessuna velleità di essere utile. Non ce l’ha, almeno per ora. In futuro, chissà.↩︎

Nessun commento:

Posta un commento

Commenta solo per dare un contributo utile, una critica costruttiva o fare un'osservazione acuta. Non commentare solo per dire che esisti anche tu o che ti piace o dispiace quello che hai letto e visto su questo blog.