behaviorresearch methods. instruments. computers 22 34-79 ... · the term micromanagement ......
TRANSCRIPT
BehaviorResearch Methods. Instruments. & Computers1990. 22 (1), 34-79
Micromanaging time: Measuring and controllingtiming errors in computer-controlled experiments
CARL P. CREEGER, KEVIN F. MILLER, and DAVID R. PAREDESUniversity of Texas, Austin, Texas
Computer-controlled experiments present a number of potential sources of error in timing thepresentation of events, including video refresh rate, keyboard scanning rate, and disk I/O times.A terminate-and-stay-resident routine implementing multiple millisecond-accuracy timers ispresented. Interfaces permitting use of the timer with several higher level languages (C, FORTRAN, Pascal, and QuickBASIC) are described, as is a design for a two- to four-button responsesystem using the computer's printer port. A general strategy is described for using multiple timersto control and measure variation in critical experimental events. A C language program is providedto benchmark variation in the time required to perform common experimental tasks (screenrefreshing, switching video pages, disk I/O, loop calculations), and results are summarized forseveral representative computers that use the IBM design.
Since at least the time of Donders (1868/1969), a standard psychological procedure has involved presenting subjects with visual stimuli and measuring the time they taketo produce some response. The advent of microcomputershas greatly facilitated studies based on this generalparadigm, but it has also introduced a number of potential errors in timing the events that are under experimental control.
The term micromanagement (leMay, Lerner, & Taylor, 1988) was coined in the 1910s (Barnhart, 1984) torefer to the detailed planning of local operations by a central executive, a practice that can have the consequenceof leaving little room for local initiative. Using personalcomputers to obtain precise timing of events requires asort of micromanagement, in which the timing of eventsis not affected by ongoing computational processes. Thepresent paper describes: (I) sources of timing errors incomputer-controlled experiments, (2) an implementationof millisecond-level timing that is both flexible and modular, (3) a strategy for using the timing routine to measureand minimize timing errors, and (4) a benchmark program for comparing the performance of experimentallyrelevant tasks on different IBM PC computers.
Sources of Timing ErrorsWhere timing errors are constant across trials, they may
be of little experimental significance, although variationsin stimulus onset asynchrony (SOA) in priming experi-
The software development reported here was supported by NSF GrantBNS-8510546 and grants of equipment from the IBM Corporation tothe second author through Project Quest. We would like to acknowledgehelpful comments on an earlier version of this paper by Nancy Lobaughand Colin MacLeod. Address reprint requests to: Kevin F. Miller,Department of Psychology, Mezes 330, University of Texas, Austin,TX 78712.
Copyright 1990 Psychonomic Society, Inc. 34
ments of as little as 100 msec can be of theoretical importance (Posner, 1978).
Time to generate stimuli. The largest timing errorsresult from ignoring the time required to generate complex experimental stimuli. Preparing a visual display onan IBM AT can easily take several hundred milliseconds.This error is likely to be constant across trials, but it islarge enough to affect the meaning of SOAs.
Video refresh rate. Computer displays are changed bya cyclical process in which each horizontal line is updatedin tum. The mechanics of screen updating pose problemsfor presenting a new stimulus at a predetermined time (Paredes, Miller, & Creeger, 1990). In particular, failure tostart timing when the stimulus is actually presented (immediately following vertical retraces) can result in maximum timing errors equal to the screen refresh interval(16.7 msec on an EGA display). One solution to theproblem of synchronizing stimulus presentation to screenrefreshes is to draw the stimulus during the interval (about1.7 msec on an EGA) when vertical retracing occurs(Dlhopolsky, 1989). For stimuli too complicated to becreated in 1.7 msec, this problem can be minimized bywriting stimulus information to an invisible graphics"page" and then making that page visible in synchronywith the start of the next screen refresh cycle. ThePSYBENCH program takes advantage of this technique,which is described in detail in Paredes, Miller, and Creeger (1990).
Disk I/O. The time required to read and write information to a hard disk depends on the arrangement of dataon the disk. The operating system (MS-DOS) assigns datato physical disk locations; it frequently breaks up files andwrites sectors wherever space is available. As the resultsof the benchmark testing reported below indicate, diskI/O results in the largest source of variable error of thosedescribed in this section. Careful program design usually
MICROMANAGING TIME 35
Db 25p cable mount
Printer Pan Switch Systemfor IBM PC family computers
FJgUre 1. Schematicdiagram for a general-purpose response switchthat can be used to connect up to four response buttons to the printerport of an ffiM PC computer. The switch features built-in debouncing of button presses, and it may be used with a variety of actualbuttons or other devices.
allows disk-intensive operations to be performed duringportions of the experiment that are not time-critical.
Keyboard and button I/O. IBM PCs and compatiblesuse a scanned matrix keyboard with a serial data connection from the keyboard to the computer. Scanning the entire keyboard takes 8 msec, which results in a variableerror of ±4 msec in measured response times and a negative bias of at least 9.2 msec in recorded times (keyboardscanning time plus a constant transmission time of1.2 msec). Graves and Bradley (1987) tested an IBM PCkeyboard and reported a mean error of 18.3 msec, witha standard deviation of 4.3 msec.
In contrast to the keyboard, the state of the parallel portcan be read directly by the PC without the concomitantscanning and transmission delays. Thus a more accuratemeasure of subjects' response times can be obtained using switches connected to a parallel port. When four orfewer switches are required, a PC-compatible printer portcan provide the necessary interface. A schematic diagramfor a simple switch box for use with a printer port ispresented in Figure 1. The switches are debounced using simple resistor-capacitor integrators. This form of debouncing results in a constant negative bias of 7 msec inrecorded times. A four-button version is presented; versions with two or three buttons can be constructed by simply ignoring the portion of the diagram connecting to pins17 (for three buttons) or 16 and 17 (for two buttons) ofthe printer port.
TIMER.COM: A Flexible, TransparentImplementation of Multiple Millisecond Timers
PC-family computers use a 16-bit counter (one thirdof an Intel 8253/8254 timer chip or an equivalent customcircuit) to generate hardware interrupts at a constant rate.The counter is loaded with a known value and allowedto count down at a fixed rate. When the count reaches0, a hardware interrupt is issued and the counter reloadsitself to repeat the process. In order to maintain constanttiming independent of processing speed, all PC computertimers count at 1.190 MHz. Normally, the timer interrupt is used by DOS to schedule time-dependent taskstypically, updating the time-of-day clock and controllingfloppy disk drive motor shutoff. PC BIOS timer routinesuse a timer value of 65536, the maximum value that canbe stored in a 16-bit counter. This provides an interruptrate of 55.2 msec.
TIMER is an assembly-language program that implements a number of useful timing functions on IBM PCcomputers (see Listing I). It is a terminate-but-stayresident (TSR) program. The software interface to TIMERuses the DOS function call mechanism; thus TIMER canbe used with any high-level language that can generatesystem calls.
TIMER increases the timer interrupt rate to one per millisecond by decreasing the value loaded into the timer chipfrom 65536 to 1193. Allowing the operating system timerinterrupt service routine (ISR) to run at the increased ratewould affect the other time-dependent operationsdescribed above, which assume that timer interrupts willoccur at the standard rate. TIMER solves this problemby emulating the standard timer interrupt. It passes control to the operating system timer ISR at nearly the expected rate (55 vs. 55.2 msec).
Running TIMER.COM from the DOS prompt installsTIMER's resident code and inserts its ISRs in the systemtimer and DOS function interrupt chains. The resident portion of TIMER occupies approximately lK of memory.For most high-level languages, access to TIMER is easiestand fastest using a language-specific assembly-languageinterface module, which translates function calls from thecalling convention of the high-level language into the format required by TIMER.
TIMER implements five timers with l-msec resolution.Two are general-purpose 32-bit timers; two implementperiodic repeating interval functions (such as AID conversion at a regular rate); and one provides timing forparallel-port connected switches and for programmedpauses. Each can be started and read independently.TIMER and its interface modules provide the following:(1) the ability to start and stop TIMER completely;(2) access to two independent, 32-bit millisecond timers,whose maximum timable period is about 2.3 million seconds; (3) repeating interval timers, which are used toschedule regularly repeating events; (4) the ability to measure response time using switches attached to a printer
1KOlIm
1 KOhm
:~IKOhm r'l SW3
T .47~
l sw 4I .4711F -= -=
- -- -
:~IKOhm r'l SWI
T.47~
l SW2T .47~ -= --=
-= -=-16
17
18
14
36 CREEGER, MILLER, AND PAREDES
port; and (5) programmed pauses of specified duration.These functions have proved to be adequate for a varietyof experimental tasks in our laboratory, including running standard chronometric and semantic priming experiments and managing external devices such as videotapecontrollers.
Interface modules have been developed for five widelyused programming languages. Listings 2-5 present interface modules and corresponding function-definition fliesfor use with Microsoft C, Microsoft FORTRAN, Microsoft QuickBASIC, and Borland Turbo Pascal.' All but theTurbo Pascal interface, which is written in Turbo Pascal,are written in assembly language.
Comparison with previous programs. A number ofapproaches to obtaining millisecond resolution timing onIDM PC computers have been described previously. Someapproaches require additional hardware (Segalowitz,1987, 1988). Crosbie (1989) has described a very different approach, based on directly reading the value of thelatched timer, which could theoretically produce timingto accuracies of about a microsecond. For most purposes,timing resolution of 1 msec is a reasonable standard thatavoids the added complexity of dealing with large valuesand inconvenient units of time.
The strategy of reprogramming the system timer toproduce millisecond-level interrupts has been describedpreviously. Several programs exist that reprogram the timing interrupts as TIMER does, but they do not pass theexpected 55-msec interrupt back to the operating system(Biihrer, Sparrer, & Weitkunat, 1987; Dlhopolsky, 1988;Graves & Bradley, 1987, 1988). This can cause difficulties for other routines that expect timing interrupts to occur at the standard rate (e.g., this interrupt is used to tumoff power to the floppy disk drive's motor after read/writeoperations), as well as cause unnecessary processing tooccur. The entire DOS timer ISR is executed every millisecond rather than every 55 msec. TIMER overcomesthese problems by limiting the processing that occurs eachmillisecond, and by passing control to the operating system ISR at the expected interval. Previous timing programs have also tended to be language-specific, to BASIC(Biihrer, Sparrer, & Weitkunat, 1987; Graves & Bradley, 1987, 1988), Turbo Pascal (Crosbie, 1989), or C(Dlhopolsky, 1988). TIMER's design allows it to be readily used with any language that can call operating systemservices, either through an assembly-language routine orby using facilities native to the language itself. TIMER'sTSR design allows it to be isolated from the user's program. Because it is nearly impossible for the higher levelprogram to disrupt TIMER, timing functions and systemintegrity are not vulnerable to bugs in user programs.
In the remainder of the paper, we will describe two usesof TIMER. The first involves a strategy for measuringand minimizing errors in the timing of events that takesadvantage of the availability of multiple timers. The second consists of a benchmark program for measuring thetime a given computer takes for performing a variety oftasks relevant to controlling psychological experiments,
and reports results for a number of different computersusing the basic IDM PC design.
A Strategy for Measuring andMinimizing Timing Errors
Experimental tasks, particularly those involving smallintervals between the presentation of successive stimuli(SOAs), consist of both stimulus processing tasks thatmust be accomplished and intervals that must be timed.Often both must be accomplished at the same time, andthe experimenter must adjust time intervals to take intoaccount time required to generate stimuli. Listing 6presents an example of how one might accomplish this,using TIMER from a higher level language. The example program, MICROMAN.C, is written in C, althoughthe same strategy could be used with other higher levellanguages. The basic procedure involves (1) starting bothtimers; (2) performing some work in preparing a stimulus display; (3) reading the first timer; (4) waiting for aninterval that represents the best estimate of the remaining time to stimulus display [(desired interval) - (elapsedtime) - (screen refresh interval)I2]; (5) presenting thestimulus on the next screen refresh; and (6) recording theactual elapsed time by reading the second timer.
The last step-recording the actual elapsed time-mayseem redundant, and in most cases it will prove to be so.lt is a simple and useful precaution, however, which canbe used to provide better control over the interval usedin Step 4 above if this is desired. The screen refresh rateimposes limits on the values that can be used for SOAs.In the worst case, in which the total elapsed time is withinthe range of variation of screen retraces, it is possible thatthe actual SOA will vary by one screen refresh interval(16.7 msec on PC ATs with EGA graphics). The interval used in Step 4 can be adjusted to eliminate anyproblem of synchronization between SOAs and screenrefresh times. Because of the limitations imposed byscreen refresh rates, actual SOAs will vary by as muchas one refresh interval from the nominal rate imposed bythe experimenter. Recording this rate will reveal if thereis any problem of variation in SOAs across trials, as discussed above, and will indicate what the constant erroris between desired and actual SOA.
MICROMAN.C introduces a random variation of100 msec in the interval between presentation of successive screens, then uses TIMER to adjust for this variation. In 100 trials on an 8-MHz IDM AT, with a desiredSOA of 300 msec, the actual SOA varied from 299 to300 msec. The same test on a PS/2 Model 80 produceda consistent SOA of 304 msec,
PSYBENCH: A Benchmark Program forExperimentally Relevant Processes
The second application of TIMER described here is aC program, PSYBENCH.C, which measures the time required to perform a number of tasks relevant to presentcomputer-controlled experiments. These are: (1) loopcomputation (a basic measure of integer processing speed,
Tab
le1
PS)'B
ench
Res
ults
for
aV
arie
tyof
Co
mp
ute
rsB
ased
onth
eIB
MPC
Des
ign
Com
pute
rP
roce
ssor
Clo
ckSI
Loo
pC
ompu
tati
onS
cree
nR
efre
shSc
reen
Dra
win
gW
ritin
gFi
leR
eadi
ngFi
leSp
eed
(Nor
ton)
Inte
rval
(MH
z)(P
C-u
nits
)M
ean
Ran
geM
ean
Ran
geM
ean
Ran
geM
ean
Ran
geM
ean
Ran
ge
8088
-bas
ed
ffiM
PC
-XT
8088
4.77
1.0
637.
063
0-64
416
.816
-17
974.
997
1-9
8710
97.4
3007
-313
629
02.0
2868
-292
1
8028
6-ba
sed
IBM
PC
-AT
8028
66
7.4
·75
170.
817
0-17
116
.816
-17
857.
985
7-85
889
8.0
814-
937
815.
880
8-82
8
IBM
PC
-AT
8028
68
8.3-
8.4
158.
815
8-15
916
.716
-17
796.
079
6·79
785
4.4
802-
909
740.
073
3-74
7
IBM
PC
-AT
8028
610
10.4
-10.
512
5.7
125-
126
16.8
16
17
633.
963
3-63
461
2.0
601-
657
624.
961
7-63
3
IBM
PS/2
mod
5080
286
101
07
1269
126-
127
14
314
-15
59
17
591-
592
7R4.
377
2-86
165
5.2
645-
661
8038
6-ba
sed
IBM
PS/2
mod
8080
386
1615
.4·1
5.5
52.0
51-5
314
.314
-15
402.
240
1-40
350
7.0
423-
549
385.
837
5-39
3
Com
paq
386-
2080
386
2024
2-24
.334
.434
·35
16.8
16-1
740
4.6
404-
405
258.
024
6-31
218
0.2
167-
189
Iden
tity
386-
2580
386
2528
.9-3
01
27.4
27-2
816
.816
-17
353.
235
3-35
414
8.4
140-
155
146.
014
3-15
0
NO
le-A
Ilun
its
are
mil
lise
cond
s.ex
cept
whe
reno
ted,
and
are
base
don
task
slim
edto
the
near
est
1rn
sec.
Des
crip
tion
ofta
sks:
SI:
Sys
tem
info
rmat
ion
prog
ram
from
Nor
ton
(198
8).
Uni
tsar
em
ulti
ples
ofth
eco
mp
uta
tio
npo
wer
of
the
orig
inal
IBM
PC.
(Res
ults
from
10tr
ials
.)L
oop
com
puta
tion
:S
ieve
ofE
rato
sthe
nes
algo
rith
mto
dete
rmin
eal
lpr
imes
<16
.38
I.(R
esul
tsfr
om10
0tr
ials
.)S
cree
nre
fres
hin
terv
al:
Tim
ebe
twee
nsu
cces
sive
vert
ical
retr
aces
.(R
esul
tsfr
om10
0tr
ials
.)S
cree
ndr
awin
g:D
raw
ing
afu
ll-s
cree
nm
uluc
olor
patt
ern
rese
mbl
ing
am
ount
ain
scen
eu
sin
gel
lips
esan
dpo
lygo
ns.
(Res
ults
from
20tr
ials
.)W
riti
ngfi
le:
Wri
ting
1.00
0lin
esea
chco
ntai
ning
one
inte
ger.
(Res
ults
from
20tr
ials
.)R
eadi
ngtil
e:R
eadi
ngth
etil
ede
scri
bed
abov
e(1
.000
lines
cont
aini
ngon
ein
tege
rea
ch)
(Res
ults
from
20tr
ials
.I
3:: n ;::0 o 3:: » z » o Z o -3 ~ rn '-.#>
-...I
38 CREEGER, MILLER, AND PAREDES
using the sieve of Eratosthenes procedure for findingprime numbers, with code from Gilbreath and Gilbreath(1983); (2) screen retrace interval (interval between successive screen retraces); (3) stimulus generation (time togenerate a variety of graphics screens varying in complexity); and (4) file I/O (time to read and write standardfiles). PSYBENCH is presented in Listing 7. It requiresan ffiM PC computer (including most clones) supportingEGA graphics (including VGA graphics devices and anumber of other systems that emulate EGA graphics).PSYBENCH has two main uses. First, it can ensure thata particular computer can perform these tasks withreasonable speed and reliability, which may be importantin selecting a computer for experimental use. Second, itprovides a meaningful benchmark of the time a particular computer requires relative to others in performing thekinds of tasks required for running psychological experiments. PSYBENCH results for a number of computersystems available at the Psychology Department of theUniversity of Texas are presented in Table 1. All computers were running MS-DOS Version 3.3. For purposesof comparison, results from the system information program (SI.COM) from Version 4.5 of the Advanced Edition of the Norton utilities (Norton, 1988) are presented.This is comparable to the loop routine in PSYBENCHin being a measure of basic processing speed, but notethat SI provides a speed index rather than a time measurement. PSYBENCH prints out additional informationabout specific subtasks; these results are provided withthe program.
Results from running PSYBENCH on a number ofdifferent computers show that in general the tasks assessedvary substantially between different systems, but that theytend to be reliable to within measurable limits (±.5 msec)on any particular computer. The obvious exception to thisresult concerns disk I/O. This is not very surprising, giventhe flexibility with which data sectors can be assigned tophysical disk locations in PC-compatible computers. Itis worth noting as a general point that although thesebenchmark tasks are similar to tasks used in many psychological experiments, these results might not be predictive for any given experimental program and computer.This is particularly true for the file I/O results, which canbe greatly affected by the overall state and capacity ofthe disk at the time that I/O occurs.
ffiM PC computers have become a ubiquitous tool forexperimental psychologists. The design of these devicescauses problems for experimenters desiring to control thepresentation of experimental events accurately, but theyare also designed such that it is possible to measure andminimize discrepancies between desired and actual timesof these events. The capacity of computers sharing thisgeneral design has also evolved substantially (as the resultsin Table 1demonstrate). Strategies for ensuring comparability of the timing of experimentally important events
across computers differing in speed and capability willbecome, if anything, more critical over time.
Program AvailabiUtyA disk containing source and executable versions of the
programs described here, additional documentation forTIMER and more detailed benchmark results can be obtained by sending a check for $15 to Kevin F. Miller. Aversion of TIMER that works with Microsoft Windowswill also be included upon request. Please specify diskformat (3.5 or 5.25 in.). Individuals who have access toelectronic mail can receive copies from Kevin F. Miller [email protected] or PSHU654@UTA3081.
REFERENCES
BARNHART, C. L. (1984). The Barnhartdictionary companion (Vol. 3,No.4). Cold Spring, NY: Author.
BUHRER, M., SPARRER, B., '" WEITKUNAT, R. (1987). Interval timingroutines for the ffiM PC/XT/AT microcomputer family. BehaviorResearch Methods, Instruments, & Computers, 19, 327-334.
CROSBIE, J. (1989). A simpleTurbo Pascal4.0 program for millisecondtiming on the ffiM PC/XT/AT. BehaviorResearch Methods, Instruments, & Computers, 21, 408-413.
DLHOPOLSKY, J. G. (1988). C languagefunctions for millisecondtimingon the ffiM PC. Behavior Research Methods, Instruments, & Computers, 20, 560-565.
DLHOPOLSKY, J. G. (1989). Synchronizing stimulusdisplays with millisecond timer softwarefor the ffiM PC. Behavior Research Methods,Instruments, & Computers, 21, 441-446.
DONDERS, F. C. (1969). On the speed of mental processes (yI. G.Koster, trans.). ActaPsychologica, 30, 412-431. (Originalwork published 1868)
GILBREATH, J., '" GILBREATH, G. (1983). Eratosthenes revisited. Byte,8, 283-326.
GRAVES, R., '" BRADLEY, R. (1987). Millisecond interval timer and auditory reaction time programs for the IBM PC. BehaviorResearchMethods, Instruments, & Computers, 19, 30-35.
GRAVES, R., '" BRADLEY, R. (1988). More on millisecond timing andtachistoscope applications for the ffiM PC. Behavior ResearchMethods, Instruments, & Computers, 20, 408-412.
LEMAY, H., LERNER, S., '" TAYLOR, M. (1988). Thefacts onfile dictionaryof new words. New York: Ballantine Books.
NORTON, P. (1988). TheNorton utilities(Version 4.5). Santa Monica,CA: Peter Norton.
PAREDES, D. R., MILLER, K. F., '" CREEGER, C. P. (1990). Graphicprecision: Displaying graphical stimuliin realtimeon IBMPCfamily computers. Unpublished manuscript, University of Texasat Austin,Department of Psychology.
POSNER, M. I. (1978). Chronometric explorations of mind. Hillsdale,NJ: Erlbaum.
SEGALOWITZ, S. J. (1987). ffiM PC Tachistoscope: Text stimuli. BehaviorResearch Methods, Instruments, & Computers, 19,383-388.
SEGALOWITZ, S. J. (1988). ffiM PC tachistoscope: II. Assembly languagesubroutines. Behavior Research Methods, Instruments, & Computers, 20, 432.
NOTE
1. Interface modules for IBM Professional FORTRAN andffiM/MicrosoftPascalare not presented,but are includedwiththe othermodules on the disk available from the authors.
MICROMANAGING TIME 39Listing I: TIMER.asm
COllll1ent 1*Copyright <c> 1989Carl Creeger202 Pickle RdAustin, Tx 78704
This Program may be distributed with out charge for any no-profit usebut may not be sold.
No Warranty, expressed or implied applies to this program.
Timer is accessed using Dos function calls. Parameters and return values arepassed to Timer by language interface routines. These routines are supplied as objectmodules and are linked with the user code. Executing Timer.Com installs Timer code,inserts the timer service routine and Timer's timer action interrupt service routineinto their respective interrupt chains. The resident portion of timer occupies about1.2 kbytes of memory. When active (no timers enabled), the timer action interruptservice routine consumes about 5% of cpu time on a stock AT. The language interfaceroutines and the timer service interrupt service routine use the following parameterpassing convention:
AH Extended Dos Timer Function code (Of0 hex).AL Call: Timer function number.
Return: Characters or switch numbers.Bx Timer values sent and returned.Cx Call: Device number.
Return: Error CodeDx = High order word for 32 bit time values.
Timer provides the following function groups and functions:
TIMER CONTROL FUNCTIONS:
START, function number 1Activates the Timer's Interrupt Service Routine and sets the system clock interruptperiod to 1 mS. Setup must be called before any other timing routines are used.Parameters: none.Return: none.
STOP, function number 2Undoes what start does. Restores the system timing routines to normal. This routineshould be called before the program exits or the system time be somewhat inaccurate.Parameters: none.Return: none.
ACKNOWLEDGE, function number 3Timer uses this function to determine whether it has already been installed.Returns Offh in AL, 0 in AH.
REPEATING INTERVAL TIMER (Type 2 Timer) FUNCTIONS:
DIN IT, function number 4Start a repeating timed period and return. Two timers are available, 1 and 2.Parameters: Device selected in CX, Time in BXReturn: illegal device returns 2 in ex.
WAIT, function number 5Holds execution until the end of the next repeating interval of a Type 2 timer.Parameters: CX =device number.
40 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
Return: Error 2, bad device number, error 3, selected delay timer has not been initializedby dinit, error 8 wait over-run.
REPORT FLAG, function number 6Get a Type 2 timer's event flag, I.E. has the next interval elapsed or not.Parameters: CX = device number.Return: 16 bit logical flag in dx, same errors as function WAIT.
CONTINUOUS TIMER (Type 1 Timer) FUNCTIONS:
START_T, function number 7Initializes a 32 bit timer, clears the timer and resets the overflow flag.Parameters: Device number in CX.Returns: Error on illegal timer number.
TIMER, function number 8Returns the present value of the specified 32 bit timer.Parameters: Device number in CX.Returns a 32 bit integer time value in DX:BX. Errors, bad timer number and timer overflow.
ASSORTED TIMING FUNCTIONS
STIME, function number 9Measure response time to a switch press. Switches are attached to a printer port.Parameters: Time-out value in BX.Returns: response time in BX, switch number in al. Cx =4 means no switch press wasdetected (Timed out).
PAUSE, function number 10Function: Delay for the time specified in parameter.Parameters: Delay, in BX, time to wait in milliseconds.Return: none.
SET_SWITCH_PORT, function number 11Select the printer port used by stime (LPT1 - LPT3). The default port is LPT1.Parameters: Cx is set to LPT# (1-3 allowed).Returns: Error 2, illegal port #, error 9, requested port not installed.
TIMER ERROR RETURNS:
The following error are reported:cx = 1, Timer not installed. This error code is returned by the interface
routine. Timer returns AH = O. The interface routine detects AH = 0returns the error code.
cx = 2, invalid device errorcx 3, wait, call to un initialized timer.cx 4, stime timed outcx =5, timer overflowcx = 6, bad function numbercx =7, Timer not startedcx =8, wait over-run.cx = 9, bad device number in call to set_switch_port.
end of comment */
MICROMANAGING TIME 41
Listing 1 (Continued)
; - -- - - - - - - - - - - - - - - - - - - - - - - - - _... - - - - --
; Con_string displays a string to the console, using dos function 9
con_string macro stringmov dx, offset stringmov ah, 9int 21h
endm
.- -- - - - - - - - - - - - - - - - - - - - - - - - - ... - - - - ---,
set veet macro int_no, old_veet, servicemav al, int_nomov ah, 35hint 21hmov word ptr old_veet, bxmov word ptr old_vect[2l, esmav dx, offset servicemov al, int nomov ah, 25hint 21h
endm
------------------------------------,
this macro tests the device number in the CL register. Ifit is neither 1 or 2, cx loaded with 2, the bad device error codeand the carry flag is set.if the device number is valid the offset of either the 1st or 2ndis loaded into the 51 register, the carry flag and the CX registerare cleared.
GetDevData macro data1, data2local deY_bad, do_2, get_end
cmp c l , 2jg deY_badcmp cl, 1j 1 deY_bad
jne do_2mov si, offset data1clcxor cx, cxjmp short get_end
do_2:mov si, o~fset data2clcxor cx, cxjmp short get_end
deY_bad:mov cx, 2stc
get_end:
endm
clear the error return
clear the error return
2 invalid device error code
42 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
._-------------------------------------.true equ 1false equ 0num_functions equ 11crlf
equequ
OdHOah
;--------------------------------------Timer Data Structures
delay
delay
clock
clock
code
struc Type 2 timersval dw ?count dw ?flag db falselate_flag db falseinited db falseends
struc Type 1 timerstime dd ?ovfl_flag db falseends
segment public 'code'assume cs: code, ds: codeorg 100h
Entry: jmp Initial izepermanent data area.
timer_running db falsedelay_' delay <>
delay_2 delay <>timer_1 clock <>
timer_2 clock <>
up_count dw ?clock_count db ?old_timer_vector dd ?old_dos_vector dd ?port dw?
function dispatcher jump address table
type 2 timers
type 1 timers
pause and stimedown counter for sys clock
evenjump_table dw
dwdwdwdwdwdwdwdwdwdwdw
?
offset STARToffset STOPoffset ACKNOWLEDGEoffset DIN IToffset _WAIToffset REPORT_FLAGoffset START_Toffset TIMERoffset STIMEoffset PAUSEoffset set_switch_port
blank address, no function #0
MICROMANAGING TIME 43
Listing I (Continued)
-**************************************************************,Timer Function Dispatcher
.**************************************************************,
This routine intercepts all dos function calls. Calls to Timercalls are directed to the timer code, normal system calls arepassed on.
ah, OfOhStart_service
Service:stipushfcmpjepopfassume ds:nothingjmp old_dos_vectorassume cs: code, ds: code
Start_service:popfpush sipush dipush espush dspush cspop ds
timer function, do it.not timer function, pass it on.
cmpjej lcmpjemovjmp
OK: cmpjg
shlpushcbwr.Jovpopcall
al,okerror_exittimer_running, trueokex, 7exit
al, num_functionserror_exit
al,ax
si, axaxj~_table[si]
no timer not running errorwhen starting the timers (funct 1)function less than 1 illegal
illegal function number
fun. num times 2 for word offset
jump to function
exit: movpoppoppoppopiret
ah, 0
dsesdisi
;indicates Timer installed.
error_exit:movjmp
cx, 6exit
bad function number
44 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
.**************************************************************,Timer Action Interrupt Service Routine
-**************************************************************,
This routine, manages all Timer actions which happen in response tothe system timer interrupt. It updates any virtual timers that areenabled. When Timer is enabled, the clock interrupt rate israised to 1 mS. When this is done, this routine passed control to theexisting Timer interrupt service routine 1 time in 55, thus maintaining theproper system clock interrupt rate.
ISR:stipushpushmovmovcmpjejmp
running:incincjnzincjnzmov
do_timer_2:incjnzincjnzmov
end_timer:cmpjnecl1'p
jnemov
not_late:decjnzmovmovmov
d 2:
axdsax, csds, axtimer_running, truerunninginactive_exit
up_countword ptr timer 1.timedo_timer_2word ptr timer_1.time + 2do_timer_2timer_1.ovfl_flag, true
word ptr timer_2.timeend timerword ptr timer_2.time + 2end timertimer_2.ovfl_flag, true
delay_1.inited, trued 2delay_1.flag, truenot latedelay_1.late_flag, true
delaL1.countd_2ax, delay_1.valdelay_1.count, axdelay_1.flag, true
re-enable interruptssave and setup
up counter for stime and pausetype 1 timers
timer 2
type 2timers
reload
set event flag (fortran true)
cmp delay_2.inited, truejne end_delaycmp delay_2. flag, truejne not_late2mov delay_2.late_flag, true
decjnzmov
delay_2.countend_delayax, delay_2.val reload
MICROMANAGING TIME 45
Listing 1 (Continued)
movmov
end_delay:
delay_2.count, axdelay_2.flag, true ; set event flag (fortran true)
dec clock_countjnz en<tISRmov c lock_count, 55
inactive_exit:pop dspop ax
assume ds:nothingjmp old_timer_vector
assume ds:code
decrement system clock counternot time for sys clock
chain to old timer isrrestore stack
movoutpoppopiret
al,20h20h,aldsax
non-chained exitsignal end of interrupt to pic
restore stack
.***************************************************************,
;subroutine: dinit (delay)public dinit
dinit proc near
GetDevOata delay_' delay_2jc dinit_exit
load_timer:elimovmovmovmovmovsti
dinit_exit:ret
dinit endp
ts i] •va l, bx[si].count, bx[silo flag, falsels i l . inited, true[si] • late_flag, false
load time value into value and counter
.***************************************************************,
; subroutine: wait
publ ic _wait_wait proc near
GetDevData delay_' delay_2jc wait_exit
cmp [si].inited, true
46 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
jemovret
no_init_error:cmpjnemovmovret
again:
no_init_errorcx, 3
[si] . late_flag, trueagain[si] . late_flag, falsecx, 8
uninited timer error code
test for late
elimov bl , [si] .flagsticmpjnzcl imovstiret
wait_exit:ret
_wait endp
bl, trueagain
[si] .flag, false
test for setjllllp if not set
;clear the event flag
.***************************************************************,
public Report_flagReport_flag proc near
GetDevData delay_' delay_2jc report_exit
cmpjemovret
get_flag:cl imovmovmovsti
[si]. inited, trueget_flagcx, 3
bl , [silo flagbh , 0
ls i l . flag, false
uninited timer error
clear the event flag
report_exit:ret
report_flag endp
.***************************************************************,
subroutine pausePAUSE proc near
public PAUSEclimov up_count, 0sti
not_yet:elimov ax, up_count
MICROMANAGING TIME 47
Listing 1 (Continued)
sticmp ax, bxjl not_yetmov cx, 0ret
pause endp
.***************************************************************.subroutine start_tstarts a continuous millisecond timer.present time returned by subroutine timer.
start_t proc nearpublic start_t
GetDevData timer_' timer_2jc start_t_exit
movmovmov
start_t_exit:ret
word ptr [si].val, 0word ptr [si] .val+2,0ls i l .flag, false ;Fortran false
;*************** Subroutine Timer ***************************************
returns the time, in milliseconds, since the latestcall to start_t for the specified timer. Time is a 32 bit integer.Timer flag is a 16 bit logical which is set to indicateoverflow of the timer.
timer proc nearpublic timer
GetDevData timer_' timer_2jc start_t_exit
bx, word ptr [si].valdx, word ptr [si] .val+ 2cl, ls i l , flagcl, trueerror ret
movmovmovcmpjeret
error_ret:movmovmov
timer_exit:ret
timer endp
ex, 5bx, 0dx, 0
; overflow error code;0 time on error
.***************************************************************,
48 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
subroutine STIME
This routine measures the elapsed from the time the routine callto the time of detection of a switch press.The routine returns the time (long integer) and switch number.
publ ic stimestime proc near
mov up_count, 0mov dx, portmov al, 20out dx, al
read_switch:mov dx, portin al, dxand al, 15xor al, 4mov cx, 1mov dl, 1
next-bit:crop al, dljz got_switchshl dl, 1inc cxcmp cx, 4j le next_bitcmp bx, up_countjg read_switchmev cx, 4ret
got_switch:mov al, elmov ah, 0mov cx, 0elimav bx, up_countmov dx, 0stiret
stime endp
zero the counterprinter control portint disable, bit 3 hi .output lines high for pull up
printer central port
mask off all but low 4 bitsinvert 3rd bit because of the portcounter for switch check loopmask value for switch check
set mask to next bit posltl0nloop counter (also switch number)
check for time outif no time out, keep checking switcheselse return timed out error.
switch number in al
clear error returnread the counter
let it count again
~***************************************************************,
subroutine STOPThis routine resets the system timer interrupt rateto defaults values.
public STOPSTOP proc near
mov timer_running, falsecl i
Reset sys clock interrupt rate.The divisor for the clock will be 0
mov al, 34hout 43h, alnap
(same as 10000H)set control word
; store ctrl word at port location
MICROMANAGING TIME 49
Listing 1 (Continued)
mov al. OOhout 40h. atnopmov at , OOhout 40h. alstimov ex. 0ret
STOP endp
; store low byte of counter divisor
store high byte of counter divisor
.*****************************.*********************************,
publ ic STARTSTART proc near
This routine sets the system clock interrupt rate to 1 mS andinitializes various (sorry 'bout that) timer variables.
cmp timer_running. trueje start_exit
set system clock interrupt rate to 1 mS.The divisor is 4a9h. The control word is 34h.
mov al.34h set timer control wordout 43h.alnopmov al,Oa9hout 40h,alnopmov al.04hout 40h.alstimov delay_L inited, falsemov delay_2. inited, falsemov del ay_1. flag, falsemoy del ay_2. flag, falsemov deLay_1.late_flag. faLsemov deLay_2.late_flag, falsemay timer_'.flag, falsemoy timer_2.flag, falsemov timer_running, true
start_exit:moy cx. 0ret
START endp
don't rush the poor timer!store low byte of counter divisor
store high byte of counter divisor
;clear error return
;***************************************************************
public ACKNO~LEOGE
ACKNO~LEOGE proc nearmov al, Offhmov ah, amov cx. 0ret
ACKNOWLEDGE endp
50 CREEGER, MILLER, AND PAREDES
Listing 1 (Continued)
w***************************************************************,
subroutine set_switch_port selects which printer port to use forswitch press detection.
set_switch_port proc nearpublic set_switch_port
cmp cl, 3jg bad_por t_mlllcmp cl, 1jl bad_port_numshl cl , 1add el, 6mov ax, 40hmov es, axmov ch, 0mov bx, cxmov ax, es: lbxlcmp ax, 0je un_instal led_portadd ax, 2mov port, axmov cx, 0ret
test for valid device number
port num * 2plus 6 = offset in BIOS Data AreaBIOS Data Area Segment
no error.
bad_port_num:movret
cx, 2 invalid device error
un_instal led_port:mov cx, 9ret
port not installed.
.***************************************************************,
end_temp_datadb If,'Error: Timer System already installed' ,cr,lf,'$'If,'Timer Sub_system version 3.21' ,cr,lf,'$'lf,'timer system installed normally' ,cr,lf,'$'
db lf,'timer system detects no printer ports' ,cr,lf,'$'dw ?
version dbnormal dbstime_warningres_flag
Initialize:jmperror
end_temp_data:call test_installedcon_string versioncmp res_flag, truejne installcon_string errorint 20h
sets res_flag if installed already
terminate
install:con_string normalmov ax, ds:2chmoves, ax
deallocate the environment block.
MICROMANAGING TIME 51
Listing 1 (Continued)
mav ah, 49hint 21h
set int21 vector
set int8 (timer) vector
moves, axmav ax, es:8cmp ax, 0jne port_olecon_string stime_warningmov ax, 0
port ole:add ax, 2
mov ax, 040h get LPT1 port address
offset from port base to status portmov port, ax
mov ds, bxmov dx, offset initiaLizeint 27H
Lowest avaiLabLe memoterminate and stay resident
.***********************************************,test_instaLLed proc near
pubLic test_instaLLedthis routine uses DOS' ability to detect an unimpLemented DOSfunction to detect previousLy instaLLed versions of TIMER.
mov ax, OfOfOhint 21hcmp al, 0jne resident
not_resident:mov res_flag, falseret
resident:mov res_flag, trueret
test installed endp
code endsend entry
;timer function ACKNOULEDGE
; set installed flag
---------------------------------- -----
Listing 2: Microsoft C Language Interface for TIMER1. timing.h - header file to be included in C programs that use TIMER.short start(void);short stop(void);short dinit(short, short);short wait(short);short report_flag(short, short *);short start_timer(short);short stime (short *, short *);short read_timer(short, long *};short stall(short);
52 CREEGER, MILLER, AND PAREDES
Listing 2 (Continued)
2. ctimer.asm - Microsoft C interface for TIMER.Copyright <c> 1989Carl Creeger202 Pickle RdAustin, Tx 78704This Program may be distributed with out charge for any no-profit use but may not be sold.No Warranty, expressed or implied applies to this program.
Use with the header file "TIMING.H"Functions implemented:
start, function numberstop, function number 2acknowledge, function number 3dinit, function number 4wait, function number 5report FLAG, function number 6start_timer, function number 7read_timer, function number 8stime, function number 9stall, function number 10set_switch_port, function number 11
CTIMER uses the file 'CMACROS.INC' version 1.06 or 5.0. At compile time this filemust be in the current directory or in a directory pointed to bythe "include" environment variable. 'CMACROS.INC' is included with theMicrosoft C compiler.
'Cmacros' allow this module to produce code for any memory model,depending on the command line used:
small model: masm /D?memS=1 /Mx ctimer,,;medium model: masm /D?memH=1 /Mx ctimer,,;compact model: masm /D?memC=1 /Mx ctimer,,;large model: masm /D?memL=1 /Mx ctimer,,:
All functions return 0 if successful, otherwise a TIMER error.See TIMER.ASM for a list of TIMER errors.
the following warning is normal and can be ignored:ctimer.ASM(99): warning A40'6: Reserved word used as symbol: WAIT
definitions to control Cmacros:?PLM=O NOT PLM (pascal and fortran) calling conventions.?WIN=O NOT Windows callable .. xlist don't list all the macros.include cmacros.inc.l i st
i----------------------------------DoTimer macro fnurnLOCAL proc_exit
mov ah, OfOhmov al, fnurnint 21h
code common to all timer interface functions.
TIMER's "DOS" function #sub function code.
MICROMANAGING TIME 53
Listing 2 (Continued)
cmpjemov
proc_exit:mov
endm
ah, 0proc_exitex, 1
ax, cx
TIMER installedTIMER not installed code
return error
-----------------------------------,
createSeg _TEXT, code, word, public, CODE, <>sBegin codeassumes cS,code
start Enable the TIMER.
cProc start,<PUBLIC>,<>cBegin
DoTimer 1
cEnd
Stop disabLe TIMER
cProc stop,<PUBLIC>,<>cBegin
DoTimer 2cEnd
dinit initialize a repeat interval timer.
cProc dinit,<PUBLIC>,<di,si>par~ timer numberparmIJ peri od
cBeginmov bx, periodmav cx, timer_numberDoTimer 4
cEnd
wait wait 'tiL end of next repeated interval
cProc wait,<PUBLIC>,<di,si>parmIJ timer number
cBeginmov ex, timer numberDoTimer 5
cEnd
report status of repeated interval timer
cProc report_flag,<PUBLIC>,<si,ds>parmIJ timer numberparmDP stat_ptr
cBeginmav cx, timer_numberDoTimer 6
if sized Data pointers for are far
54 CREEGER, MILLER, AND PAREDES
Listing 2 (Continued)
mov ds, dxmov si, off_stat_ptr
elsemov si, stat_ptr
endifmov ts i l , bx
cEnd
start timer start a timer.
cProc start_timer,<PUBLIC>,<di,si>parmY timer number
cBeginmov ex, timer_numberDoTimer 7
cEnd
return current value of timer.
cProc
cBegin
read_timer,<PUBLIC>,<si, ds>parrnU timer_numberparmDP timer_value
mov ex, timer_numberDoTimer 8
if sizedmov si, seg_timer_valuemov ds, simov si, off-timer_value
elsemov si, timer_value
endifmov ts i] , bxmov ls i + 2] , dx
cEnd
if large data modelget seg of timer_value
offset of timer parameter
offset of timer parameter
return time lswreturn time msw
Stime -------- measure switch response time
cProc stime,<PUBLIC>,<di,si,ds>parmDP time_vaiueparmDP switch_number
cBeginif sized
mov si, seg_time_valuemov ds, simov si, off- time_value
elsemov si, time_value
endifmov bx, ls i l
mov ah, OFOhmov al, 9
int 21hcmp ah, 0je stime_exitmov ex, 1
stime_exit:mov ts i] , bx
offset of time parameter
offset of time parameter
stime's function number.
Timer not installed code
return time value
MICROMANAGING TIME 55
Listing 2 (Continued)
if sizedmov si, se9_switch_numbermov ds, simov si, se9_switch_number
elsemov si, switch_number
endifmov ah, 0mov [s u. axmov ax, ex
cEnd
address of switch parameter
address of switch parameter
return error code
Stall --------- pause.
cProc stall,<PUBLIC>,<di,si>parmIJ time_val
cBeginmov bx, time_valmov dx, 0DoTimer 10
cEnd
get the time value
Select printer port to user with stime.
cProc set_port,<PUBLIC>,<di,si>parmIJ port_num
cBeginmov ex, port_numDoTimer 11
cEndsEndend
Listing 3: Microsoft FORTRAN Language Interface for TIMER
1. timer.fi - FORTRAN include file for programs that use TIMER.interface to function start()
integer*2 sl.artend
interface to function stopti()integer*2 stopti
end
interface to function dinit(NumTi, rate)integer*2 dinitinteger*2 NumTiinteger*2 rate
end
interface to function wait(NumTi)integer*2 waitinteger*2 NumTi [reference]
end
56 CREEGER, MILLER, AND PAREDES
Listing 3 (Continued)
interface to function report(NumTi, flag)integer*2 reportinteger*2 NumTilogical*2 flag
end
interface to function startt(NumTi)integer*2 starttinteger*2 NumTi
end
interface to function stime (time, NumSw)integer*2 stimeinteger*2 timeinteger*2 NumSw
end
interface to function timer(NumTi, time)integer*2 timerinteger*2 NumTiinteger*4 time
end
interface to function stall(time)integer*2 stallinteger*2 time
end
interface to function swport(portnum)integer*2 swporti nteopr*? ""rt", 1m
2. timer.fd - FORTRAN function definition file to be included in subroutines.
integer*2 start[EXTERN]integer*2 stopti[EXTERN]integer*2 dinit[EXTERN]integer*2 wait[EXTERN]integer*2 report[EXTERN]integer*2 startt[EXTERN]integer*2 stime [EXTERN]inteQer*2 timer[EXTERN]
3. msftimer.asm - TIMER interface for Microsoft FORTRAN.
copyright <c> 1989Carl Creeger202 Pickle RdAustin, Tx 78704
This Program may be distributed with out charge for any no-profit usebut may not be sold.
No Warranty, expressed or implied applies to this program.
interface from Microsoft Fortran to the "Timer" timing system
MICROMANAGING TIME 57
Listing 3 (Continued)
for information on TIMER's interface, see timer.asm.Use with interface definition file TIMER.FI in each module that uses TIMER,
and TIMER.FD in each subroutine that calls TIMER functions.
Assemble :masm msftimer ,,;
the following warning is normal:msftimer.ASM(85): warning A4016: Reseryed word used as symbol: ~AIT
.model large
.codefor use with large (default> memory model programs.
._-_._-------------~--------------------,
entry macropush bpmoy bp, sppush dspush sipush di
endm
exit macro sizepop dipop sipop dspop bp
ret sizeendm
errJet MACROLOCAL proc exit
cJllljemov
proc_eXit:moy
ENOM
ah, 0proc_exitex, 1
ax, ex
Timer installedTimer not installed code
return error
DoTimer macro fnummov ah, OfOhmoy al, fnumint 21herr-ret
endm
;---------------------------------------
start procpublic start
OoTimerret
start endp
Timer's "DOS" function codesub function code.
start the Timer
58 CREEGER, MILLER, AND PAREDES
Listing 3 (Continued)
..... _--- .... -----------------_ ... ---------------------------------,
stopti procpublic stopti
DoTimer 2ret
stopti endp
stop the Timer.
0 ----------------------------------------------- _,
dinit procpubl ic dinit
entrylds si, [bp + 10]
mov ex, ts i]lds s i , lbp + 6]
mov bx, lsi]mov dx, 0
DoTimer 4exit B
dinit endp
; initialize a delay timer.
timer number
time value (16 bits incoming)clear msw of 32 time returns
;----------------------------------------------------------------
wait procpubl i c waitentrylds s i , Ibp + 6]mov ex, lsi]
DoTimer 5exit 4
wait endp
timer number
-----------------------------------------------------------------,
report procpubl i c reportentryIds si, [bp + 10]
mov ex, rs i] timer numberDoTimer 6
Ids si, [bp + 6]
mov [s u. bxexit B
report endp
._---------------------------------------------------------------,
startt procpubl icentryldsmov
startt
s i , lbp + 6]ex, [s i] timer number
MICROMANAGING TIME 59
Listing 3 (Continued)
DoTimer 7exit 4
startt endp
4 • _
,
timer proc
publ ic timerentrylds si, [bp + 10]mov ex, ts i]
DoTimer 8lds si, [bp + 6]mov (s i l , bxmov ls i + 2], dxexit 8
timer endp
timer number
return time value lswreturn time value msw
;------------------------------------------------------------._--
stime procpubl ic stimeentrymov ah, OfOhmov al, 9mov di, bx
lds si, [bp + 10]mov bx, [s i]int 21h
err- retlds si, [bp + 6]mov ls i l , bxmov word pt r Is i +
lds si, [bp + 10]mov ah, 0mov ts i) , axexit I.l
stime endp
2], 0
timer's DOS function codefunction number
timeout value
test and return error
return time value lswreturn time value msw
;----------------------------------------------------------------
stall procpubl ic stallentrylds si, lbp + 6]mov bx, ts i] time value (16 bits incoming)mov dx, 0 clear msw of 32 time returns
DoTimer 10exit 4
stall endp
60 CREEGER, MILLER, AND PAREDES
Listing 3 (Continued);a __ .. . _
swport procpublic swport
entrylds si, [bp + 6]mov ex, [s i1
DoTimer 11exit 4
swport endp
end
; select switch port.
por t nl.ll'ber
Listing 4: Microsoft QuickBASIC Language Interface for TIMER
1. timer.bi - QuickBASIC include file
1_ ... ... TIMER.BI : Timer system interface Include File ----
Copyright <c> 1989Carl Creeger202 Pickle RdAustin, Tx 78704
This Program may be distributed with out charge for any no-profit usebut mey not be sold.
No Warranty, expressed or implied applies to this program.
This include file defines the functions used to interfaceto the timing system "TIMER.COM". It provides the DECLAREstatements for the assembly language routines START,STOPTI, DINIT, MS_WAIT, REPORT_FLAG, START_TIMER, STIME,READ_TIMER, STALL, and SET_PORT
I _ _ __ _ - _ - - - _ ...
DECLARE FUNCTION START%
DECLARE FUNCTION STOPTI%
DECLARE FUNCTION DINIT% (BYVAL devnum AS INTEGER, BYVAL dtime AS INTEGER)
DECLARE FUNCTION MSWAIT% (BYVAL wtime AS INTEGER)
DECLARE FUNCTION REPORTFLAG% (BYVAL devnum AS INTEGER, SEG flag AS INTEGER)
DECLARE FUNCTION STARTTIMER% (BYVAL devnum AS INTEGER)
DECLARE FUNCTION STIME% (SEG swnum AS INTEGER, SEG time AS INTEGER)
DECLARE FUNCTION READTIMER% (BYVAL devnum AS INTEGER, SEG time AS LONG)
DECLARE FUNCTION STALL% (BYVAL time AS INTEGER)
DECLARE FUNCTION SETPORT% (BYVAL portnum AS INTEGER)
MICROMANAGING TIME 61
Listing 4 (Continued)
2. qbtimer.asm - TIMER interface for Microsoft QuickBASIC
qbtimer.asmMicrosoft OuickBasic v4.5 interface to the "Timer" timing system.
Copyright <c> 1989Carl Creeger202 Pickle RdAustin, Tx 78704
This Program may be distributed with out charge for any no-profit usebut may not be sold.No Warranty, expressed or implied applies to this progr~m.
use with include file 'TIMER.BI'
Functions implemented:FUNCTION START%FUNCT ION STOPT 1%FUNCTION DINIT% (BYVAL START AS INTEGER, BYVAL dtime AS INTEGER)FUNCTION MSWAIT% (BYVAL wtime AS INTEGER)FUNCTION REPORTFLAG% (BYVAL tinum AS INTEGER, SEG flag AS INTEGER)FUNCTION STARTTIMER% (BYVAL tinum AS INTEGER)FUNCTION STIME% (SEG swnum AS INTEGER, SEG time AS INTEGER)FUNCTION READTIMER% (BYVAL tinum AS INTEGER, SEG time AS LONG)FUNCTION STALL% (BYVAL time AS INTEGER)FUNCTION SETPORT% (BYVAL portnum AS INTEGER)
public start, stopt;, din;t, mswait, reportflagpublic starttimer, readtimer, stime, stall, setport
Assemble :masm qbt imer" ;
._--------------------------------------,
entry macropush bpmov bp, sppush dspush sipush di
endm
exit macro sizepop dipop sipop dspop bpret size
endm
Timer's "DOS" function #sub function code.
ah, OfOhal , fnum21h
movint
DoTimer macro fnumLOCAL proc_exit
mov
62 CREEGER, MILLER, AND PAREDES
Listing 4 (Continued)
cmpjemoy
proe exit:moy
endm
.modeL medium•code
ah, 0proc_exitex, 1
ax, ex
Timer instaL LedTimer not instaLLed code
return error
· ~ ----- -_ .. -- _.- ------ - ---- - ----------·start proc
OoTimerret
start endp
·---- ------- - --- ------- --------------- -- - - - - --·stopt; proc
Ootimer 2ret
stopti endp
._--------------------------------------------·dinit proc
entrymoy ex, [bp ... 8] timer nlmlbermoy bx, [bp'" 6) time value (16 bits incoming)moy dx, 0 eLear msw of 32 time returns
DoT imer 4exit 4
dinit endp
----------------------------------------------,
mswait proeentrymov cx, Ibp ... 6] timer number
Ootimer 5exit 2
mswait endp
----------------------------------------------,
reportflag proeentrymovmoy
di , bllex, [bp'" 10] timer nl.lllber
DoTimer 6
Ids s i , [bp'" 6]
mov lsi], bxellit 6
reportflag endp
MICROMANAGING TIME 63
Listing 4 (Continued)
.. -----------------------------------------.--,
starttimer proeentrymov ex, [bp + 6]Dotimer 7
exit 2starttimer endp
timer m.mOOr
readtimer proeentrymov di, bxmov cx, [bp + 10]Dotimer 8
timer nlll1ber
ldsmovmovexit
readtimer
si, [bp + 6]
tsn , bx(s i + 2], dx6endp
return time value lswreturn time value msw
;---------------------------------------------
stime procentrymov ah, OfOhmov al, 9lds s i , [bp + 10]mov bx, ts i]int 21hcmp ah, 0je stime_exitmov cx,
stime_exit:lds si, (bp + 10]mov [s1), bxlds si, [bp + 6]mov ah, 0mov Is i l , axmov ax, cxexit 8
stime endp
Timer's DOS function codefunction nunber
timeout value
Timer installed
Timer not installed code
return time value lsw
return error code
;---------------------------------------------
stall proeentrymov bx, [bp + 6]mov dx, 0DoTimer 10exit 2
sral I endp
time value (16 bits incoming)clear msw of 32 time returns
64 CREEGER, MILLER, AND PAREDES
Listing 4 (Continued)
;---------------------------------------------
setport Pf'OC
entrymav cx, [bp + 6] poI' t n\lli)eI'
DoTimer 11
exit 4setport endp
;---------------------------------------------end
Listing 5: TP'TIMER.PAS: Turbo Pascal Interface to TIMER
i. IPTIMER.PAS
unit tptimer;{This is an interface to the miLLisecond timing routine "timer"See the fiLe timer.doc for detaiLs.
Copyright <c> 1989CarL Creeger202 PickLe RdAustin, Tx 78704
This Program may be distributed with out charge for any no-profit usebut may not be sold.
Wo ~arranty, expressed Dr implied applies to this program. )
(**************)interface
uses dOs;
{ Functions impLemented: }FUNCTION start : integer;FUNCTION stop : integer;FUNCTION dinit(dev_num, delay_vaLue: integer) integer;FUNCTION wait(dev_num : integer) : integer;FUNCTION report_fLag(device_num integer; val' status: boolean)
: integer;FUNCTION start_timer(device_num integer) integer;FUNCTION read_timer(device_num : integer; val' timer_value: Longint)
: integer;FUNCTiON stime (val' time, switch_number: integer) integer;FUNCTiON staLl(stalL_time : integer) : integer;FUNCTION set_port(port : integer) : integer;
impLementation
{-------------------------------------}
MICROMANAGING TIME 65
Listing 5 (Continued)
FUNCTION start
var
integer;
regs registers;
beginregs.ah := SOfO;regs. a l : = 1;intr ($21, regs);
if (regs.ah <> 0) then beginstart := 1;
end else beginstart:= regs.ax;
end;end;
{---------------------------------------------)
FUNCTION stop: integer;
varregs registers;
begin
Regs.al :'" 2;regs.ah :'" Sf0;
intr (S21, regs);
if (regs.ah <> 0) then beginstop := 1;
end else beginstop:= regs.ax;
end;end;
{ timer systems "DOS" function # }{ sub function code. }
{---------------------------------------------)
FUNCTION dinit(dev_num, delay_value: integer) : integer;var
regs : registers;
beginregs.cx .'" dev_num;regs.bx :== delay_value;regs.dx .'" Q.,
Regs.al -= 4;regs.ah:= Sf0;
intr ($21, regs);
if (regs.ah <> 0) then begindin;t:= 1;
{ device number}
66 CREEGER, MILLER, AND PAREDES
Listing 5 (Continued)
end else begindinit:= regs.ax;
end;end;
{.... _-----------------------_._._----_._ .... _}
FUNCTION wait(dev_num : integer) : integer;var
regs registers;
beginregs.ex := dev_num;Regs.al := 5',regs.ah .- $fO;
intr ($21. regs);
if (regs.ah <> 0) then beginwait:= 1;
end else beginwait:= regs. ax;
end;end;
{---------------------------------------------}
FUNCTION report_flag(deviee_num : integer; var status boolean): integer;
varregs registers;
beginregs.ex := deviee_num;Regs.al := 6;regs.ah := $fO;
intr ($21, regs);
if (regs.bx = 0) then beginstatus := false;
end else beginstatus := true;
end;
if (regs.ah <> 0) then beginreport_flag:= 1;
end else beginreport_flag:= regs_ax;
end;end;
{ device number}
{---------------------------------------------}
FUNCTION start_timer(deviee_num : integer) : integer;
MICROMANAGING TIME 67
Listing 5 (Continued)
varregs registers;
begin
7·,regs.ex
Regs.al :=regs.ah := Sf0;
intr ($21, regs);
if (regs.ah <> 0) then beginstart_timer:= 1;
end else beginstart_timer:= regs.ax;
end;end;
{-----_ ..... _-------------------_.--------_ .. _)
FUNCTION read_timer(device_num : integer; var timer value: integer;
varregs registers;
beginregs.cx := device_num;Regs.al := 8;regs.ah .- Sf0;
intr (S21, regs);
if (regs.ah <> 0) then beginread_timer:= 1;
end else beginread_timer:= regs.ax;
end;
timer_value := regs.bx;end;
{-_._----------_ .. _------------------------_ .. )
longint)
FUNCTION stime (var time, switch_number: integer)
varregs registers;
beginregs.ah := SOfO;regs.al := 9',regs.bx := time;
intr ($21, regs) ;
integer;
68 CREEGER, MILLER, AND PAREDES
Listing 5 (Continned)
if (regs.an <> Q)
stirne :=end else begin
stirne :=end;
time := regs.bx;
then begin
1;
regs.ax;
switch_number .- regs.ax;end;
{---------------------------------------------}
FUNCTION stall(statl_time : integer) : ;ntege~;
val'
regs registers;
beginregs.bx :=regs.dx :=Regs.at .regs.an :=
intI' <$<:'1,
stall_time;0;i.,SfD;
regs);
end;
if (regs.an <> 0)stall ;=
end else beginstall :=
end;
tnen begin1;
regs.ax;
{---------------------------------------------)
FUNCTION set_port(port : integer) : integer;
val'
regs registers;
beginregs.cx := port;Regs.al := 1;regs.an ~= Sf0;
intI' {$21, regs);
if (regs.an <> 0) the~ beg\~
set_port:=c ';emf else begin
set_port:= regs.ax;end;
end;end.
MICROMANAGING TIME 69
Listing 6: MicroMan.C: A Strategy for Measuring and Minimizing Timing Errors
#include <stdio.h>#include <stdlib.h>#include <graph.h>#include <time.h>
/******* declarations for timing routines ****************/short far start(void);short far stop(void);short far start_timer(short);short far read_timer(short, long *);short far stall(short);/******* color code definitions *****************************/# define RED 4# define MAGENTA 5# define BRO~N 6# define ~HITE 7# define LT_~HITE 15
#define SOA#def ine REFRESH#define DUMMY_RESPONSE_TIME
300L /* intended SOA */16.7 /* average screen refresh time for EGA */120
/******** poll port for change in retrace status ********/void ret race( )(
while(!(inp(Ox3da) &8»while( inp(Ox3da) &8) ;
}
/******** generate dummy prImIng stimulus ********/void draw_priming_stim(int page)(
_setactivepage(page);_setcolor(BRO~N);
_rectangle(_GFILLINTERIOR, 256, 140, 384, 210);_setcolor(LT_~HITE);
_rectangle(_GFILLINTERIOR, 266, 150, 374, 200);}
/******** generate dummy target stimulus ********/void draw_target_stim(int page)(
_setactivepage(page);_setcolor(MAGENTA);_rectangle(_GFILLINTERIOR, 256, 140, 384, 210);_setcolor(~HITE);
_rectangle(_GFILLINTERIOR, 266, 150, 374, 200);_settextcolor(RED);_settextposition(12,37);_outtext(IXXXXXXX");_settextposition(13,37);_outtext(IOOOOOOO") ;_settextposition(14,37);_outtext("XXXXXXXU);
70 CREEGER, MILLER, AND PAREDES
Listing 6 (Continued)
1******** simulate response *********************1void get_response(){
}
time_t clocktimeimaine)(
1* for seeding random number generator *1
long time1, time2, time3i
1* add random time (0-100 msec) to overhead *11* generate target stimulus off screen *11* get overhead time *11* wait intended SOA minus overhead minus
1/2 refresh rate *11* wait for beginning of refresh cycle *1/* display target stimulus *11* get actual soa interval *1
1* get seed *11* seed *11* initialize timer setup *11* set graphic mode *1
time(&clocktime)isrand(clocktime)is tar tt j ;
_setvideomode(_ERESCOLOR)idraw_priming_stim(O);start_timer(1)istart_timer(2);stall(rand()%100)idraw_target_stim(1)iread_timer(1,&time1)istall(SOA-time1-REFRESH/2)i
retraceC) ;_setvisualpage(1);read_timer(2,&time2);start_timer(1)igetJesponse()iread_timer(1,&time3)istoP()i /* stop timing routines *1_setvideomode(_DEFAULTMOOE)i /* return to text mode */printf(lt\nlntended SOA = %ld Actual SOA = %ld", SOA, time2);printf(lt\nOverhead =%ldlt,time1)i
}
Listing 7: PsyBench.c: A Benchmark Program for Experimentally Relevant Tasks
1*---------------------------------------------------- - -- - - - - - - - - - - - - - - - - - - -* PsyBench.c: Benchmark program for recording elapsed times for ...* Screen Refreshing* Generating Graphical Displays* Disk (File) 1/0 (Writing/Reading)* Computing (Eratosthene's Sieve for Finding Primes)
** History:
***
specifications: August, 1989, Kevin Miller, University of Texas at AustinWritten September, 1989, David Paredes, U. T. AustinAssembly language timer modules (ctimer.obj & timer.com)written by Carl Creeger, U. T. Austin
** Compiler: Microsoft C version 5.0* Compile statement: CL -c psybench* Linked: Ctimer.obj* Link statement: link /NOE psybench ctimer;
*
MICROMANAGING TIME 71
Listing 7 (Continued)
* Hardware:*
IBM PC or PS/2 with EGA or VGA (or compatible)
* Dependency: timer.com must be invoked before program execution
** Output: times.out*--------------------------------------------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <graph.h>#include <math.h>#include <bios.h>#include <timing.h>
#define LOOP#define MAXLINE#define STALLTIME#define ESC
201000SOOO1
/* number of main loops *//* maximum # of read-write lines for disk i-o
/* stall time to read intro &test timer *//* scan code for escape key */
test */
#define PutText(row,col,string) _settextposition«row),(col»; _outtext«string»
#define T BLACK#define T_BLUE#define T_GREEN#define T CYAN#define T RED#define T_MAGENTA#define T BROWN#def ine T IIH ITE#define T GRAY#define T_LT_BLUE#define T_LT_GREEN#define T_LT_CYAN#define T_LT_RED#define T_LT_MAGENTA#define T_YELLOII#define T_LT_IIHITE
o /* color code definitions */1
23456789101112131415
/* global arrays for storing times */double retraces[S], screen1[5], screen2[S], screen3[S], screen4[S], sieves[S];double wri t el Ifil , wri te2 [S], wri te3 [5], read1[S], read2 [5], read3 [S];
enum stat { N, MIN, MAX, SUM, SUMSQ}; /* mnemonics for variables to be stored */FILE *outfile, *tmpl, *tmp2, *tmp3; /* output &temporary files *//********* Fatal Error Exit ***************/void ErrExit(ErrMessage)
char * ErrMessage;{
_setvideomode(_DEFAULTMOOE);
printf("\n%s", ErrMessage);exit (1);}
/********* check for escape key ***************/void check_esc(){
if(kbhitO)if«(_bios_keybrd(_KEYBRD_READ) &OxffOO) » 8)==ESC)
ErrExit("\nProgram terminated by user.");
72 CREEGER, MILLER, AND PAREDES
Listing 7 (Continued)
}
/********* Accumulate timing values. ************/
void AccumStats (data, time)double data [] ;long time;
{
data[N]++;if(data[N]==1) data[MIN]=time;data[MINJ=min(data[MIN],time);data[MAXl=max(data[MAXl,time);data [SUMl =data[SUM]+{time);data [SUMSOl =data[SUMSQ]+(time*time);
}
/********* test timing *********************/void test_timer(timeout)
int timeout;{
long time;
start_timer(1);stall(timeout);read_timer(1,&time);if«time-timeout) > 1 II (timeout-time) > 1)
ErrExit ("\nError: Time.com not invoked or not running correctly.II);}
/********* open output & temp files ********/void open_files(){
if( (outf i le=fopen{ "times.out", "W") )==NULL)ErrExit ("ERROR: Could not open output file");
if«tmp1=fopen(ltmp1 1,lw+"»==NULL)
ErrExit ("ERROR: Could not open temporary file #1");
if{(tmp2=fopen("tmp2","w+"»==NULL)ErrExit ("ERROR: Could not open temporary file #2");
if( (tmp3=fopen("tmp3", "w+"))==NULL)ErrExit ("ERROR: CouLd not open temporary file #3");
}
/********* wait for change in retrace status ****/void retracet ){
while(!(inp(Ox3da) & 8»while( inp{Ox3da) & 8)
; /* waits for a retrace on *//* waits for a retrace off */
}
/********* time between retraces: screen refresh rate ********/void do_retrace{){
long time;
retrace();start_timer(1);retraceO;read_timer(1,&time);AccumStats (retraces, time);
}
Listing 7 (Continued)
f********* construct introduction screen ******************fvoid draw intro (page)
int page;(
_setactivepage(page);_setcolor(T_BlUE);_rectangle(_GFlllINTERIOR,O,O,640,350);_setbkcolor(_BlUE);PutText (2,32,"MICRO MANAGING TlME");PutText (6,34,"Carl Creeger");PutText (8,33,"Kevin F. Miller");PutText <10,32,"David R. Paredes");PutText (14,24,"Tne University of Texas at Austin");
f········· generate display # 1 •••••••••••••••••••••••••••/void draw_screen1 (page)
int page;{
unsigned cnar • mask=("x20x08x20x08x20x08x20x08"};long time;
start_timer(1);_setactivepage(page);_setcolor(T_RED);_setfillmask(mask);_rectangle(_GflllINTERIOR,O,O,640,350);_setfillmask(NUll);PutText (25,35," SCREEN 1 II);
read_timer(1,&time);AccumStats (screen1, time);
}
/ ••••••••• generate display # 2 •••••••••••••••••••••••••••/void draw_screen2 (page)
int page;(
long time;
start_timer(1);_setactivepage(page);_setcolor(T_BlUE);_rectangle(_GFIllINTERIOR,O,O,640,350);_ffiOveto(O,350);_setcolor(T_lT_BlUE);_lineto(80,300);_lineto(140,325);_I ineto(240, 280);_lineto(300,300);_lineto(320,295);_lineto(340,300);_lineto(500,270);_lineto(640,330);_lineto(640,350);_I ineto(O,350);_floodfill(1,1,T_lT_BlUE);_setcolor(T_YEll~);
_ellipse(_GFlllINTERIOR,370,90,485,170);
MICROMANAGING TIME 73
74 CREEGER, MILLER, AND PAREDES
Listing 7 (Continued)
_setcolor(T_WHITE):_ellipse(_GFILLINTERIOR,200, 150,450, 160):_ellipse(_GFILLINTERIOR,430,130,600,140};PutText (25,35," SCREEN 2 ");read_timer(1,&time};AccumStats (screen2, time):
}
1********* generate display # 3 ***************************1
void draw_screen3(page)int page;
(
long time;
start_timer(l);_setactivepage(page);_setcolor(T_MAGENTA):_rectangle(_GFILLINTERIOR, 256, 140, 384, 210);_setcolor(T_WHITE);_rectangle(_GfILLINTERIOR, 266, 150, 374, 200);_settextcolor(T_RED);PutText <i2,37,"XXXXXXXU):PutText (13,37, "0000000");PutText (14,37,"XXXXXXX"):Putiext (25,35," SCREEIl 3 II);
read_timer(l,&time};AccumStats {screen3, time};
}
1********* generate display # 4 ****·····**··*···*·***·····****11* (copy stimulus from display # 3 to memory & write it 25 *11* times to the active page *//******.****************************************************/
void draw_screen4(source_page,dest_page)int source_page, dest_page;
(
int x, v;char * ibuffer;long time;
start_timer(1);_setactivepage(source_page);ibuffer = malloc«unsigned int)_imagesize(256, 140, 384, 210»;if (! ibuffer)ErrExit ("ERROR: Not enough memory to copy image");_getimage(256, 140, 384, 210,ibuffer};_setactivepage(dest_page);for(y=0;y<=350;y~=69) (
for(x=O;x<=640;x+=127)_putimage(x,y,ibuffer,_GPSET);
}
free( ibuffer);PutText (25,35," SCREEN 4 II);
read_timer{1,&time);AccumStats (screen4, time);
}
/*********** write black box to entire page ******************/void clr_page{page)
int page;
MICROMANAGING TIME 75
Listing 7 (Continued)
_setaetivepage(page);_seteolor(T_BLACK);_reetangLeC_GFILLINTERIOR,O,O,640,350);
}
/*********** generate dummy data for file write & read ******/long avar[MAXLINE], bvar[MAXLINE], evar[MAXLINE];void generate_dataC)(
int i;
for(i=O;i<MAXLINE;i++)avar[il=i; bvar[i]=i+i; evar[i]=i*i;
}
/*********** write dummy data to file # 1 ****************/void write_file1()(
long time;
int i;
start_timer(1 );for (i=O;i<MAXLINE;i++)
fprintf<tmp1,I%Ld\n",avar[i] );read_timer(1,&time);AceumStats (write1, time);
}
/*********** write dummy data to fiLe # 2 ****************/void write_file2()(
Long time;int i;
start_timer(1);for (i=O;i<MAXLINE;i++)
fprintfCtmp2,"%ld %Ld\n",avar[il,bvar[il);read_timer(1,&time);AccumStats Cwrite2, time);
}
/*********** write dummy data to file # 1 ****************/void write_fiLe3C)(
long time;int i;
start_timer(1);for (i=O;i<MAXLINE;i++)
fprintf(tmp3,"%Ld %ld %ld\n",avar[i],bvar[il,evar[il);read_timer(1,&time);AeeumStats Cwrite3, time);
}
/********* rewind temporary fiLes for reading or rewriting **********/void rewind_fiLesC)(
rewindCtmp1);rewindCtmp2);rewindC tmp3);
76 CREEGER, MILLER, AND PAREDES
Listing 7 (Continued)
/************ read file 1 ************************/void read_fi lel O(
long time,tmpnum1;
start_timer(1 );wh i le« fscanf (tmp}, "%ld\n". &trnpnum1) != EOF)read_timer(1.&time);AccumStats (read1. time);
)
/************ read file 2 ************************/void read_file2()(
long time,tmpnum1.tmpnum2;
start_timer(1);while«fscanf(tmp2."%ld %ld\nll.&tmpnum1.&tmpnum2» != EOF)read_timer(1.&time);AccumStats (read2. time);
)
/************ read file 3 ************************/void read_file3()(
long time, trnpnum'l , tmpnum2. tmpnLJll3;
start_timer(1);while«fscant<tmp3."%ld %ld %ld\n".&trnpnum1,&tmpnum2.&tmpnum3» != EOF)
read_timer(1.&time);AccumStats (read3. time);
/************ use DOS command to delete temp files *************/int system(const char *);
void delete_files()(
system("del tmp?");)
/********* time computations: adapted from/* Eratosthenes Sieve Prime Number Program in C. Byte January/* The code has been corrected to produce primes correctly.#define TRUE 1#define FALSE 0#define SIZE 8190
char flags[SIZE+1J={O};
void run_sieve()(
register int i.k;int count;long time;
*/1983. */
*/
start_timer(1);count = 0;fore i = 0; i <= SIZE; i++) flags[iJ TRUE; /* set all flags true */
MICROMANAGING TIME 77
Listing 7 (Continued)
fore i = 2; i <= SIZE; i++ ) {if ( flags[il) {
for ( k = i + i; k <= SIZE; k +=flags[kl = FALSE;
count++:)
}
read_timer(1,&time);AccumStats (sieves, time);
1* found a prime *1
1* Cancel its multiples *1
}
1******* calc. mean and Std_dev and Print one line of the report. ************1void DoPrint (file, szLabel, data, flag)
FILE * fi leichar * szLabel;double data (];short flag: 1* one prints to screen and file, 0 only to screen. *1
(
double Mean, Std;static char Fmt(]="\n%-14.14s r.3.0f %5.0f %5.0f r~.2f r.6.2f" ;
Mean=data[SUMl/data[Nl;Std=sqrt«data[SUMSCl/data[Nl)-( (Mean)* (Mean»);fprintf(file, Fmt, sZLabel, data[Nl,data[MIN1,data[MAX1,Mean,Std);if (flag) printf(Fmt, szLabel, data[NJ,data[MIN1,data[MAXJ,Mean,Std);}
1********* calculate totals &write to screen and output file ************1void write_report(}{
double mean, std, screentime, writetime, readtime, tot_time:static char label (J =" Test N Min Max
screentime=screen1 [SUM1+screen2[SUMJ+screen3[SUM1+screen4[SUM1;writetime=write1 [SUM1+write2[SUM1+write3[SUM1;readtime=read1 [SUM1+read2[SUM1+read3[SUM1;tot_time=retraces[SUM1+screentime+writetime+readtime+sieves[SUMl;
Mean STO";
printf("\n\n\n\n-----------REPRESENTATIVE STIMULI GENERATION & DISK liD TIMES----------------");fprintf(outfile,"----··_····_··----------- STIMULI GENERATION & DISK liD TIMES----------------");printf(II\n -- TIMES ARE IN MILLISECONDS --\n");fprintf(outfi le,"\n -- TIMES ARE IN MILLISECONDS --\n");printf ("\n%s", label);fprintf (out f i le, "\n%s", label):
DoPrint (outfi le, "Loop Coq:>Ute", sieves, mean, std, 1) ;DoPrint (outfile, "Screen Refresh", retraces, mean, std, 1):DoPrint (outfile, "Screen1", screen1, mean, std, 0):DoPrint (outfile, "Screen2", screen2, mean, std, 1) ;DoPrint (outfi le, "Screen3", screen3, mean, std, 0) ;DoPrint (outfi le, "Screen4", screen4, mean, std, 0);DoPrint (outfi le, "lJrite File1", write1, mean, std, 1) ;DoPrint (outfi le, "lJrite File2", write2, mean, std, 0) :DoPrint (outfile, "lJrite File3", write3, mean, std, 0) ;DoPrint (outfile, "Read File1", read1, mean, std, 1);DoPrint (outfi le, "Read File2", read2, mean, std, 0):DoPrint (outfile, "Read File3", read3, mean, std, 0) ;
78 CREEGER, MILLER, AND PAREDES
Listing 7 (Continued)
printf("\n\nTOTAL OF TEST TIMES (IN MINUTES): %-8.4f",tot_time/60000);fprintf<outfi le,"\n\nTOTAl OF TEST TIMES (IN MINUTES): %-8.4f", tot_time/bOOOO);printf("\n-----------------------------------------------------------------------------");fprintf(outfile,"\n-----------------------------------------------------------------------------11);printf<"\n\nAdditional information is recorded on fi le times.out\n");
}
/************ MAIN PROGRAM *****************1mainO{
short mainloop, i;
startO;_setvideomode(_ERESCOLOR};draw_intro(O};test_timer(STALLTIME);check_escO;open_fllesO;
1* initialize tImIng routines *11* color display 640 x 350 pixels *1
for(mainloop=O; mainloop < LOOP; mainloop++) (do_ret raceO;check_esc();draw_screen1(1);dOJetrace();_setvisualpage(1);checkesct J;generate_data();write_fi le10;check_escO;draw_screen2(0);dOJetrace();_setvisualpage(O);checlc_esc{);wrlte_fi le2();for(i=O;i<1D;i++) run_sieve();ct r_page(1 );draw_screen3(1);checK_esc();do_retrace();_setvisualpage(1);clr_page(O);check_esc{);write_fi le30;rewind_files();read_fi le30;check_esc();draw_screen4(1,O);do_ret raceO;_setvisualpage(O);
}
Listing 7 (Continued)
read_fi le'();check_esc();read_fi le2();rewind_fi lesO;cl r_page( , );
}
delete_fi lesO;stop(); /* stop timing routines */_setvideomode(_OEFAULTMOOE);write_report();
(Manuscript received October 5, 1989;revision accepted for publication February 2, \990.)
MICROMANAGING TIME 79