
FB II Compiler
PG PRO
Debugging
Memory
System
Mathematics
Resources
Disk I/O
Windows
Controls
Menus
Mouse
Keyboard
Text
Fonts
Drawing
Sound
Clipboard
Printing
Communication
ASM
|
MATHEMATICS
Set delays in milliseconds
The following example was posted a couple of months ago. It includes a minor refinement: a correction term gMSOverhead (set in FN MeasureMSOverhead) that improves the accuracy of the delay on slow machines. You could remove all mention of gMSOverhead on any reasonably fast machine, i.e. if the overhead reported by this program is much less than the delays you actually want.
'--------------A Complete FB2 Program----------------
COMPILE 0,_dimmedVarsOnly
DIM RECORD anyOldNameAtAll
DIM mSHi&,mSLo&
DIM END RECORD.microSecRecord
DIM gMSOverhead&
END GLOBALS
LOCAL FN Microseconds (mSRecPtr&)
` move.l ^mSRecPtr&,-(sp)
` dc.w $A193 ; 68k trap word
` move.l (sp)+,a1
` move.l a0,(a1)+
` move.l d0,(a1)
END FN
LOCAL FN MeasureMSOverhead
DIM myMS1.microSecRecord, myMS2.microSecRecord, j
FN Microseconds(@myMS1)
FOR j=1 TO 1000
FN Microseconds(@myMS2)
NEXT
gMSOverhead& = (myMS2.mSLo&-myMS1.mSLo&)/1000
END FN
LOCAL FN DelayMicroSeconds (delayMicrS&)
' Waste time (up to _maxlong'!47483647 microseconds).
' Accuracy is best for delayMicrS& at least a few hundred.
DIM myMS1.microSecRecord, myMS2.microSecRecord
' compensate for time calling FN Microseconds
delayMicrS& = delayMicrS& - gMSOverhead&
IF delayMicrS&<=0 THEN EXIT FN
'calculate what time to wait until
FN Microseconds(@myMS1) 'read the timer
LONG IF ((myMS1.mSLo& + delayMicrS&) < myMS1.mSLo&)
INC(myMS1.mSHi&) ' addition caused carry
END IF
myMS1.mSLo&=myMS1.mSLo& + delayMicrS&
DO 'waste time in this loop
FN Microseconds(@myMS2) 'poll the timer
UNTIL (myMS2.mSLo&>=myMS1.mSLo&) AND (myMS2.mSHi&>=myMS1.mSHi&)
END FN
' demo main program
DIM ticksWas&, ticksNow&, microSecDelayWanted&, j
WINDOW 1
FN MeasureMSOverhead
PRINT "Overhead = " gMSOverhead& " microseconds"
microSecDelayWanted&= 5 * 1000 ' 5 ms
ticksWas&=FN TICKCOUNT
FOR j=1 TO 200 ' do 200 individual delays
FN DelayMicroSeconds(microSecDelayWanted&)
NEXT
ticksNow&=FN TICKCOUNT
PRINT ticksNow&-ticksWas&" ticks elapsed"
DO: HANDLEEVENTS: UNTIL FN BUTTON
'--------------------------------------------------------
Robert Purves
'=================
'timing in microseconds
LONG FN MicroSeconds&
` dc.w $A193 ; trap word
END FN' returns low longword of 8-byte result
'=================
Don't use the tiny FN above (for which I claim, or perhaps admit, responsibility). It was devised for minimum overhead, and worked OK in FB2, but for FB^3 you need something better.
The program below shows the proper syntax, allowing 68K, PPC or FAT.
Note that the components of the microSecRecord are defined as the new FB^3 type UNSIGNED LONG. The definition unfortunately reveals a bug in release 0 of FB^3: it cannot print variables of that type.
You can print them with the help of the STR$ function, but _another_ bug is revealed: the UNSIGNED nature is lost. Since microSecLo counts MOD 4294967296, it has a period of 4294.967296s (about 71 minutes). STR$(myMS.microSecLo) therefore displays as a positive number for 35 minutes then negative for 35 minutes. The UNS$ function correctly displays myMS.microSecLo as always positive, but it shouldn't be necessary to use UNS$ on an already UNSIGNED variable.
'----------------------------------------------------------
BEGIN RECORD microSecRecord
DIM microSecHi AS UNSIGNED LONG
DIM microSecLo AS UNSIGNED LONG
END RECORD
TOOLBOX Microseconds (LONG) `0xA193,0x225F,0x22C8,0x2280
/* what those 0x values mean in 68K
dc.w $A193 ;0xA193
move.l (sp)+,a1 ;0x225F
move.l a0,(a1)+ ;0x22C8
move.l d0,(a1) ;0x2280
*/
LOCAL FN ShowTime
DIM myMS as microSecRecord
DEFSTR LONG
FN Microseconds(@myMS)
' Next line doesn't compile - comment it out
'PRINT myMS.microSecHi, myMS.microSecLo ' BUG
' STR$ should show unsigned values, but doesn't - another BUG
PRINT STR$(myMS.microSecHi), STR$(myMS.microSecLo)
' At last...a way to show the unsigned longs
PRINT UNS$(myMS.microSecHi), UNS$(myMS.microSecLo)
END FN
WINDOW 1
ON TIMER(1) FN ShowTime
DO
HANDLEEVENTS
UNTIL FN BUTTON
'----------------------------------------------------------
Robert Purves
See below. For a delay in milliseconds, just call FN DelayMicroSeconds(millisecs*1000). This works in 68K or PPC, and on a machine of any speed. There's no need for an initial testing function, since the Time Manager uses an internal fixed-rate clock.
'--------------------------------------------------------
BEGIN RECORD microSecRecord
DIM microSecHi AS UNSIGNED LONG
DIM microSecLo AS UNSIGNED LONG
END RECORD
TOOLBOX Microseconds (LONG) `0xA193,0x225F,0x22C8,0x2280
LOCAL FN DelayMicroSeconds(delayMicrS&)
' waste time (up to _maxlong!47483647 microseconds)
DIM myMS1 as microSecRecord, myMS2 as microSecRecord
IF delayMicrS&<=0 THEN EXIT FN
'calculate what time to wait until
FN Microseconds(@myMS1)
LONG IF (myMS1.microSecLo + delayMicrS& < myMS1.microSecLo)
inc(myMS1.microSecHi) ' addition caused carry
END IF
myMS1.microSecLo=myMS1.microSecLo + delayMicrS&
DO 'waste time in this loop
FN Microseconds(@myMS2)
UNTIL (myMS2.microSecLo>=myMS1.microSecLo) AND (myMS2.microSecHi>=myMS1.microSecHi)
END FN
' demo main program
DIM microSecsAsked&,ticksWas&, ticksNow&
WINDOW 1
microSecsAsked&=1000000
ticksWas&=FN TICKCOUNT
FN DelayMicroSeconds(microSecsAsked&)
ticksNow&=FN TICKCOUNT
PRINT "Requested delay = " microSecsAsked&/16666 " ticks"
PRINT "Measured delay = " ticksNow&-ticksWas&" ticks"
DO
HANDLEEVENTS
UNTIL FN BUTTON
'--------------------------------------------------------
Robert Purves
|