Higher Resolution Timer
Higher Resolution Timer
Anyone know of a way to execute tasks at a higher resolution than milliseconds?
I need to send some data at very specific intervals... 2.4ms, .4ms, 1.2ms and .8ms, which means GetTickCount_() is not accurate enough.
Ideas? Suggestions?
Thanks.
I need to send some data at very specific intervals... 2.4ms, .4ms, 1.2ms and .8ms, which means GetTickCount_() is not accurate enough.
Ideas? Suggestions?
Thanks.
Re: Higher Resolution Timer
> Anyone know of a way to execute tasks at a higher resolution than milliseconds?
According to Microsoft, the QueryPerformanceTimer API has a resolution of
microseconds, as opposed to milliseconds; but the frequency depends on the
PC being used. See http://support.microsoft.com/kb/q172338/ for details.
According to Microsoft, the QueryPerformanceTimer API has a resolution of
microseconds, as opposed to milliseconds; but the frequency depends on the
PC being used. See http://support.microsoft.com/kb/q172338/ for details.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
I converted some code from the ^MS link provided by PB^ and it seems to work. It uses a hi-res timer to time a Delay(1000) call. I get results ranging from 0.995139 to 1.000909 seconds for the 1 second delay.
This is new territory for me so DO NOT take this snippet as 100% accuate
This is new territory for me so DO NOT take this snippet as 100% accuate

Code: Select all
Procedure.s HiResTimer(xNum)
Ctr1.LARGE_INTEGER
Ctr2.LARGE_INTEGER
Freq.LARGE_INTEGER
Overhead.LARGE_INTEGER
A.l
i.l
If QueryPerformanceFrequency_(Freq)
QueryPerformanceCounter_(Ctr1)
QueryPerformanceCounter_(Ctr2)
Overhead\lowpart = Ctr2\lowpart - Ctr1\lowpart ; determine API overhead
QueryPerformanceCounter_(Ctr1) ; start time loop
Delay(xNum)
QueryPerformanceCounter_(Ctr2) ; end time loop
TimerInfo$ = "Delay(" + Str(xNum) + ") took " + StrF((Ctr2\lowpart - Ctr1\lowpart - Overhead\lowpart) / Freq\lowpart) + " seconds"
result$ = TimerInfo$
Else
result$ = "Error occured"
EndIf
ProcedureReturn result$
EndProcedure
MessageRequester("Hi_Res Timer", HiResTimer(1000))
What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
I need to send pulses down the LPT port.
Switch on for 2.4ms
Switch off for .4ms
Switch on for 1.2ms
Switch off for .8ms
etc.
Various sequences of these on/off (0 volt/5 volt) control a device. The times must be exact to conform to a specific protocol.
So I guess I would need something to determine how many loop it takes for 1ms (based on speed of computer), then count loops to create 2.4ms delay, .4ms delay, etc.
Switch on for 2.4ms
Switch off for .4ms
Switch on for 1.2ms
Switch off for .8ms
etc.
Various sequences of these on/off (0 volt/5 volt) control a device. The times must be exact to conform to a specific protocol.
So I guess I would need something to determine how many loop it takes for 1ms (based on speed of computer), then count loops to create 2.4ms delay, .4ms delay, etc.
Hi Paul,
It's not PureBasic but may be of help...
Lots of other timer source code at this site, hope it helps.
Regards,
Marc
It's not PureBasic but may be of help...
http://www.powerbasic.com/support/forum ... 02208.htmlThis code provides high resolution timing into the microsecond realm, much better than GetTickCount() which is generally in the 10's of milliseconds (10,000's of microseconds):
Use at your convenience. I tested this code on a win98 system and it worked, too. Not sure whether that can be counted upon though.
Also compiles with PB/CC, just replace the msgbox calls with stdout.
Lots of other timer source code at this site, hope it helps.
Regards,
Marc
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
I think i've got it.
Perhaps this can help you Paul (see the last part):

Perhaps this can help you Paul (see the last part):
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: "+StrF(periodns)+" nanosecs")
Else
MessageRequester("","No High-res timer allowed"):End
EndIf
; determine API call delay:
QueryPerformanceCounter_(Ctr1.LARGE_INTEGER)
QueryPerformanceCounter_(Ctr2.LARGE_INTEGER)
calldelay.LARGE_INTEGER\lowpart = Ctr2\lowpart - Ctr1\lowpart
MessageRequester("","API call used time was ~ "+StrF(calldelay\lowpart*periodns)+" nanosecs")
; determine for-next loop time:
QueryPerformanceCounter_(Ctr1.LARGE_INTEGER)
For t=1 To 100000:Next
QueryPerformanceCounter_(Ctr2.LARGE_INTEGER)
MessageRequester("","for-next loop used time was ~ "+StrF((Ctr2\lowpart-Ctr1\lowpart-calldelay\lowpart)*periodns)+" nanosecs")
; perform about 1.234567 millisecond delay:
ticks.f=1.234567/periodns.f
ticks.f*1000000
QueryPerformanceCounter_(Ctr1.LARGE_INTEGER):Ctr1\lowpart&$7FFFFFFF
Repeat
QueryPerformanceCounter_(Ctr2.LARGE_INTEGER):Ctr2\lowpart&$7FFFFFFF
Until Ctr2\lowpart-Ctr1\lowpart+calldelay\lowpart>=ticks.f
MessageRequester("","OK!")
Last edited by Psychophanta on Sun Dec 19, 2004 12:22 pm, edited 1 time in total.
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
This way is more accurate:
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 delay:
QueryPerformanceCounter_(Ctr1.LARGE_INTEGER)
QueryPerformanceCounter_(Ctr2.LARGE_INTEGER)
calldelay.LARGE_INTEGER\lowpart = Ctr2\lowpart - Ctr1\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!")
Last edited by Psychophanta on Sun Dec 19, 2004 12:21 pm, edited 1 time in total.