Page 1 of 1

Hi-res timing delayer

Posted: Sat Dec 18, 2004 8:32 pm
by Psychophanta

Code: Select all

;-determine timer max resolution:
If QueryPerformanceFrequency_(Freq.LARGE_INTEGER)
  periodns.f=1000000000/(Pow(2,32)*Freq\highpart+Freq\lowpart)
  ;MessageRequester("","Resolution (used time per tick) in this machine is: "+Str(periodns)+" nanosecs")
Else
  MessageRequester("","No High-res timer allowed"):End
EndIf

;-determine API call and other stuff delay:
!fldz
!fldz
QueryPerformanceCounter_(t1.LARGE_INTEGER)
     ;Same stuff than below (needed to determine the time amount used by testing process):
!fild qword[v_t1]
!fsub st0,st1
!fcomip st2
!jc @f
!@@:
!fstp st0
!fstp st0
QueryPerformanceCounter_(t2.LARGE_INTEGER)
calldelay.LARGE_INTEGER\lowpart = t2\lowpart - t1\lowpart
;MessageRequester("","API call used time was ~ "+StrF(calldelay\lowpart*periodns)+" nanosecs") 


;-perform hires-timing delay:
Standby.f=ValF(InputRequester("","Input wished delay time in milliseconds","0.655"))
Standby.f*1000000;    <- pass nanosecs to millisecs

!fld dword[v_Standby]
!fdiv dword[v_periodns]; <-now in st0 is the #ticks to perform
QueryPerformanceCounter_(t1.LARGE_INTEGER)
!fild qword[v_t1]   ;<-now in st0 is checkpoint1,in st1 is #ticks
!fsub qword[v_calldelay]  ;<-substract the time used by QueryPerformanceCounter_() function call
!@@:
QueryPerformanceCounter_(t2.LARGE_INTEGER)
!fild qword[v_t2] ;<-now in st0 is checkpoint2, in st1 is checkpoint1 and in st2 is #ticks
!fsub st0,st1   ;<- checkpoint2 - checkpoint1 - calldelay to st0
!fcomip st2     ;<-compare #ticks
!jc @r          ;<-continue polling until #ticks is reached
!fstp st0
!fstp st0


MessageRequester("","That's it!")
Corrected for final, i hope.
I don't know if it can be done even more accurate :)

Posted: Mon Dec 20, 2004 11:42 pm
by eriansa
could by very usefull. Thanks!

Posted: Tue Dec 21, 2004 1:48 am
by vanleth
great stuff, thanks

Re: Hi-res timing delayer

Posted: Thu Jul 15, 2010 12:28 pm
by Psychophanta
Hi-res timming stuff:

Code: Select all

; determine timer max resolution:
If QueryPerformanceFrequency_(@Freq.q)
  If Freq<0:Freq!$8000000000000000:periodns.d=Freq:periodns+$7fffffffffffffff+1:periodns=1E9/periodns
  Else:periodns=1E9/Freq
  EndIf
  MessageRequester("Timing resolution info","Resolution (used time per tick) in this machine is: "+StrD(periodns)+" nanosecs")
Else
  MessageRequester("Sorry!","No High-res timer allowed by this machine"):End
EndIf

; determine API call delay:
QueryPerformanceCounter_(@t1.q)
QueryPerformanceCounter_(@t2.q)
calldelay.q=t2-t1
MessageRequester("","Used time by API call QueryPerformanceCounter_() was ~ "+StrD(calldelay*periodns)+" nanosecs")

; determine for-next loop time:
QueryPerformanceCounter_(@t1.q)
For t=1 To 100000:Next
QueryPerformanceCounter_(@t2.q)
MessageRequester("","(For t=1 To 100000:Next) loop used time was ~ "+StrD((t2-t1-calldelay)*periodns)+" nanosecs")

; perform some microsecond delay:
#uSecDelay=188.765432
ticks.d=#uSecDelay/periodns
ticks*1E3
QueryPerformanceCounter_(@t1.q)
Repeat
  QueryPerformanceCounter_(@t2.q)
Until t2-t1+calldelay>=ticks
MessageRequester("End","~ "+StrD(periodns*(t2-t1+calldelay)/1E3)+" microseconds delayed")