Newsgroup: it.comp.lang.pascal
Titolo: Delay di precisione

A scuola sto facendo un progetto su un controllo software molto semplice per
motore passo-passo, deve solo comandare gli IC appositi da parallela.
Pero' ho un problema, cioe' quello di creare il clock per far steppare il
motore, dovrei avere un periodo a partire da 2.5Ms (con una discreta
risoluzione) e il pascal non ha nessuna funzione per stoppare un programma
piu' precisa di delay (ke piglia valori interi di millisecondo), qualcuno di
voi conosce un modo rapido software per fare un delay piu' preciso?
io avevo approcciato in due modi
1 - fargli fare un ciclo a vuoto per moooolte volte misurare il tempo che
passa con chiamate all'orologio di sistema e calcolare una costante sul
numero di cicli a vuoto da fare x 0.1 Ms di pausa, ma non ha funzionato
2 - fare la stessa cosa in asm calcolando i cicli macchina per ogni
passaggio in modo da avere un valore mooolto accurato
3 - chiamare l'in15 (mi pare) che dovrebbe dare la possibilita' di generare
pause fino a 900nS ma sul NT mi pare non si possa usare, e io devo lavorare
su un PC con NT
4 - Copiare dal kernel di linux la procedura di timing (quella che calcola i
bogomips all'avvio) , ma scarterei a priori
5 - questo l'ho letto su internet: leggere un dato sul bus in modo che passi
un tempo costante
Voi che suggerite?
--
Keita'
--
ATI drivers on Linux, firmate la petizione!
http://www.petitiononline.com/xf123456/petition-sign.html
?

 Voi che suggerite?
Se puoi usare le API del SO qualche funzione migliore la trovi
di sicuro. Ad esempio le API Win32 mettono a disposizione
QueryPerformanceFrequency e QueryPerformanceCounter, che hanno
una precisione nettamente superiore ai millisecondi.
Oppure, se puoi utilizzare un po' di assembly, ci sarebbe
l'istruzione RDTSC (solo con CPU di classe pentium e successive).
Praticamente ad ogni ciclo di clock viene incrementato un
contatore a 64 bit, con RDTSC puoi leggere tale contatore
(il risultato viene messo in EDX EAX).
La precisione ovviamente dipende dalla frequenza della CPU
(1/(frequenza CPU)), con appositi calcoli puoi ottenere
un delay molto preciso, con un processore a 100MHz ottieni
quindi una precisione di 0.01 microsecondi (1/(100*10^6)).
Altrimenti... boh :)


Avevo sentito di questo registro, buono a sapersi che l'istruzione e' RDTSC
pero' il programma dovrebbe essere indipendente dal processore, e io non
saprei come calcolarne la velocità anche se probabilmente da qualche parte
si dovrebbe poter leggere il clock, avete qualche link a una cosa che tratti
bene questi argomenti?
A scuola queste cose non le insegnano, anzi... a scuola di usano reg a 16
bit =(


 l'istruzione RDTSC (solo con CPU di classe pentium e successive).
Mi autorispondo per una precisazione...
Ovviamente ho scritto "classe pentium" per intendere
la tipologia della CPU, che poi sia intel o amd poco
importa, dovrebbe essere presente un po' ovunque, ma
non essendomi mai interessato in modo particolare alla
questione non ho dati certi alla mano.

 bene questi argomenti?
Beh, come leggere il clock direttamente non saprei in questo
momento. Comunque sia ci vuole poco, leggi il valore fornito
da RDTSC, fai un delay di N secondi (e questo puoi farlo
con una funzione a tuo piacere, una precisione al millisecondo
e' sufficiente), rileggi il valore fornito da RDTSC, fai la
differenza dei due valori ed ottieni il numero di cicli di
clock avvenuti in N secondi.
Oppure? Aspetti un interrupt 8, leggi il valore di RDTSC,
aspetti il successivo interrupt 8, rileggi il valore di
RDTSC, fai la differenza dei valori ed ottieni il numero
di cicli di clock in (circa, il valore esatto non lo ricordo)
55 millisecondi.

 una precisione nettamente superiore ai millisecondi.
questa mi sembra la soluzione piu' comoda... pero' anche qua la
frequenza varia da macchina a macchina... se hai letto dove ho letto
io, quella che viene chiamata "risoluzione di 0.8 microsecondi"
indica la "durata" della chiamata della funzione e quindi il piu'
piccolo intervallo identificabile; se il processore va piu' piano,
diciamo che la funzione ritornera' piu' volte lo stesso risultato,
quindi la frequenza sara' piu' bassa :-\
[di certo meglio 1000hz :-) ]
[ che velocita' ha la parallela ?  dovrebbe essere costante... non
puo' sparare fuori roba continuata calcolando la "lunghezza d'onda"
in byte ? :-) ]
-- 
Dreadnaut
(Life would be easier if I had the source code)

 Voi che suggerite?
un clock hardware esterno :-)  a parte gli scherzi, per le frequenze da
te richieste non so' quanto in pascal si possa fare....
o asm o win come dice Bane.


 un clock hardware esterno :-)  a parte gli scherzi, per le frequenze da
eheheh, piu' che uno scherzo era la prima ipotesi, solo che poi il prof mi
ha detto che il driver me lo dava lui gia' fatto e non ci sono possibilita'
di modifiche, senno' era una cavolata con un DAC e un convertitore V/f
facevo tutto il progetto in meno di un ora...


 facevo tutto il progetto in meno di un ora...
non e' che magari il driver ha un qualche tipo di simil-timing automatico?
il prof che ha detto del problema ?
-- 
Dreadnaut
(signless again)


piuttosto di interpellare il prof riprogetto tutta l'interfaccia+driver
partendo da zero (che poi usando i dirver integrati viene una cavolata) =)
Voglio prendermi la soddisfazione di arrivarci da solo (o cmq quasi da solo,
nessuno nasce imparato) , perche' so gia' che lui mi direbbe "lascia stare"
mentre io voglio stupire con effetti speciali (penso che alla fine usero'
RDTSC oppure riprogrammo il timer di sistema, o senno' veramente mi faccio
una periferica esterna per la generazione della forma d'onda, tanto e' un
attivita' di laboratorio, in piu' quest'ultima soluzione mi lascerebbe piu'
liberta nel programma senza dover dare sempre un occhiata che i cicli non
superino un TOT di tempo che senno canno la temporizzazione)
ps = sinceramente se fosse stato possibile a scuola avrei usato il c+ linux
in modo da creare 2-3 processi diversi senza incasinarmi la vita... ma la
scuola e' indietro di milllle secoli =(


 clock avvenuti in N secondi.
Avevo 10 minuti liberi e cosi' ho provato a buttare
giu' qualche riga di codice (Free Pascal),
stilisticamente forse poteva venir meglio, ma l'ho
scritto proprio al volo :)
Dato che sembrerebbe funzionare (almeno sul mio PC
rileva il dato esatto) ho pensato potesse tornare
utilie anche a qualcun altro... non si sa mai :)
{$ASMMODE intel}
Program Test;
Uses Crt;
Function GetRDTSC: QWord;
Var H, L: Cardinal;
    R: QWord;
Begin
   Asm
   RDTSC
   Mov H, EDX
   Mov L, EAX
   End ['EDX', 'EAX'];
   R := H;
   R := R Shl 32 + L;
   GetRDTSC := R;
End;
Function GetFreqCPU: Word;
Var N1, N2: QWord;
Begin
   N1 := GetRDTSC;
   Delay(1000);
   N2 := GetRDTSC;
   GetFreqCPU := (N2-N1) Div 1000000;
End;
Begin
   WriteLn('CPU: ', GetFreqCPU, ' MHz');
End.