Newsgroup: it.hobby.elettronica.digitale
Titolo: si può fare meglio?

Ciao,
ho due motori passo passo collegati a una porta di un uC. Sono
configurati come unipolari per cui ne controllo uno con il primo nibble
e l'altro con il secondo nibble della porta del micro.
Dovendo muoverli in modo indipendente ho scritto questa funzioncina per
evitare che la scrittura sul registro della porta modifichi anche il
nibble riservato all'altro motore:
motMask = (0x0F << (4 * !input(MOTOR))) & input_d();
output_d(stepSeq[motPhase] << (4 * input(MOTOR)) | motMask);
il pin MOTOR stabilisce quale motore devo muovere. La porta d è quella
dove sono appunto collegati i due motori  la variabile
stepSeq[motPhase] contiene la combinazione corrente delle fasi attive
del motore.
Praticamente salvo la configurazione del motore "fermo" in motMask e la
riporto tale e quale in uscita aggiornando il motore in "movimento".
Mi chiedevo se si può fare di meglio in termini di eleganza ma
soprattutto di efficienza del codice.
Grazie!
Marco / iw2nzm

output_d(stepSeq[motPhase] << (4 * input(MOTOR)) | motMask);
...
Entro solo oggi in questo ng... ma questa domanda mi ha "intrigato".
Se ho capito bene... hai 2 bit per ogni motore, su di un'unica porta da 8 
bit, e vuoi pilotarli in modo indipendente. I 2 bit di ogni fase sono in un 
array. Per rendere il tutto più efficiente, prova a cambiare proprio l'array 
delle fasi, sdoppiandolo per i due motori. Supponendo, per semplicità, che 
contenga:
in binario:
00 fase 0
01 fase 1
10 fase 2
11 fase 3
puoi raddoppiare i valori (metto degli spazi, solo per chiarezza):
00 00 fase 0 motore a
00 01 fase 1 motore a
00 10 fase 2 motore a
00 11 fase 3 motore a
00 00 fase 0 motore b
01 00 fase 1 motore b
10 00 fase 2 motore b
11 00 fase 3 motore b
Questo ti evita lo shift (<<), sempre che cambi l'indice del motore da 0/1 a 
0/4 (sennò devi fare MOTOR*4):
stepSeq[motPhase + MOTOR]
Per la maschera, idem... creati un altro array (mask) con i valori binari 
(con spazi per chiarezza):
11 00 <- entry 0
11 00
11 00
11 00
00 11 <- entry 4
00 11
00 11
00 11
Basterebbero due soli elementi, ma così puoi usare lo stesso indice MOTOR 
0/4. Ecco che ti resta solo da fare:
motMask = mask[MOTOR] & input_d();
output_d( stepSeq[motPhase + MOTOR] | motMask);
Sicuramente è più leggibile e forse anche più veloce (questo dipende dalla 
CPU usata, dal compilatore ecc. ecc. ecc.). Il tutto è facilmente adattabile 
ad un uso con 4 bit invece di due.
Stefano

 output_d( stepSeq[motPhase + MOTOR] | motMask);
In effetti la tua soluzione mi sembra senz'altro più snella e penso 
anche più efficiente da un punto di vista di esecuzione.
Ha come svantaggio la maggior richiesta di RAM perchè occorre allocare 
due array char da 8 elementi ciascuno, totale 16 byte. Se non sono 
stretto con la RAM proverò senz'altro a implementarla, anzi... magari lo 
faccio ugualmente per verificare che funzioni a dovere!
Grazie della dritta!
Marco / iw2nzm

 ugualmente per verificare che funzioni a dovere!
Se funziona, fammelo sapere ;)
Comunque, da buon programmatore assembly, eccoti una dritta per risparmiare 
qualche byte: dell'array mask usi solo due valori. Nelle altre posizoni, 
puoi metterci ciò che vuoi, ad esempio altre costanti del tuo programma. Gli 
ultimi tre valori, comunque, puoi anche non allocarli, tanto non verranno 
mai indirizzati. Per chi non c'ha capito nulla:
11 00 <- entry 0
...valore libero...
...valore libero...
...valore libero...
00 11 <- entry 4
...valore libero...
...valore libero...
...valore libero...
Facciamoci del male. Se l'ultima fase del motore a fosse proprio 11 (o 1111 
a 4 bit), potresti fare un'ottimizzazione "pazzesca", usando un solo array 
da 9 byte:
11 00 <- entry 0
fase 0 motore a
fase 1 motore a
fase 2 motore a
00 11 <- entry 4 = fase 3 motore a
fase 0 motore b
fase 1 motore b
fase 2 motore b
fase 3 motore b
motMask = mask[MOTOR] & input_d();
output_d( stepSeq[motPhase + MOTOR + 1] | motMask);
Ma perderesti molto in leggibilità....
Stefano

 da 9 byte:
LOL! :)
Ottimizzazioni del genere possono essere utili nel caso di prodotto 
finito, collaudato e funzionante... nel mio caso non ha senso poiché è 
ancora il prototipo... Però l'idea che c'è alla base non è affatto stupida!
Continuando a farsi del male, viene da chiedersi se ha senso allocare 
comunque i 6 byte in più (anche se destinati ad altri valori) 
incasinando la leggibilità del codice oppure allocare solamente i due 
valori necessari e eseguendo un'operazione in più ad ogni chiamata 
(MOTOR * 4 o meglio MOTOR << 2). Io propendo per la seconda ipotesi :)
Marco / iw2nzm

 (MOTOR * 4 o meglio MOTOR << 2). Io propendo per la seconda ipotesi :)
Se si tratta di costanti, andrebbero a finire nella stessa zona di memoria 
del programma. In un PIC,. finirebbero nella memoria flash, ad esempio. I 6 
byte che risparmi li perderesti per le istruzioni di shift. Se si tratta 
invece di valori che salvi nella ram o nella eprom, fai comunque uno 
"scambio" tra occupazione di byte della memoria dati e di quella programma, 
quindi non otterresti alcun vantaggio.
Per avere ottimizzazioni veramente spinte sarebbe utile conoscere i valori 
delle fasi, magari sono ottenibili da una formula semplice che richiede meno 
memoria che questa versione programma+array. Se poi programmi in assembly, 
invece che in C, puoi veramente spremere fino all'ultimo byte...
Stefano