Tips: Keypress

by Denis Pelli

VideoToolbox
PsychToolbox
Tips
 
speed
displays
how to
mac software
bibliographies

visitors since September 17, 1996.
December 26, 1997

HOW TO MEASURE THE TIME OF A KEYPRESS (REACTION TIME)

With standard Mac hardware there are three ways to record the time of a keypress:

  1. Call the Event Manager. This is too slow for accurate human reaction-time measurements.
  2. Call GetKeys(). This has an accuracy of ±8 ms, which is good enough for measuring human reaction times, since the human observer's standard deviation is much larger than 8 ms.
  3. Call the ADB Manager. This is used by the KeMo and SuperLab Pro packages (see below) to achieve an accuracy of ±2 ms.

The Psychophysics Toolbox includes several MEX functions (callable from MATLAB, written in C) to retrieve keypresses and the time of keypress. GetChar and CharAvail are character-oriented (and slow), based on the Mac OS Event Manager. KbCheck and KbWait are keypress-oriented (and relatively fast), based on the Mac OS GetKeys function. Complete C sources are available. Free.

Dan Costin's free KeMo package includes a good discussion--reproduced below from his 1993 document--of the various ways of measuring keypress time on a Mac and their temporal precision. The package includes C sources that use the ADB Manager (I think) to achieve accuracy of ±2 ms.

Finally, Hisham Abboud recently (12/97) wrote to MacPsych with a good summary--reproduced below--confirming what Dan Costin says, and including up-to-date information about new Macs. SuperLab Pro is a commercial product.


Accuracy Issues

Reproduced from "KeMo 1.5 Reference" by Dan Costin, dated September 11, 1993

The KeMo timer has a resolution of about 20 microseconds. The function KeMoTimerStop() returns elapsed time rounded off to the nearest millisecond.

ADB (Apple Desktop Bus) keyboards, mice, and other devices, however, cannot report key and mouse button presses nearly as fast. While theoretically (i.e., according to Apple technical specifications) ADB devices can be asked about their keys and buttons every 2 msecs or so, in reality there is some overhead in moving that data around from chip to chip until it can be examined by a program. During normal operation, a Mac checks ADB devices about every 11 msecs or so. If they have some data, that data is then transferred from the ADB device to the Mac. This all leads to a resolution of 16 msecs or more for the detection of events on ADB devices. Furthermore, if a program checks for these events using the EventManager, there is possibly additional time until an event is put on the event queue and until your program detects the event.

KeMo bypasses the higher levels of processing normally used to detect ADB events and achieves a polling rate of slightly less than 4 msecs on most Mac II's (with the appropriate constant correction that results in an accuracy of ±2 msecs). There is some variation in this rate: on a Mac IIfx the polling rate is less than 3 msecs (accuracy is ±1.4 msecs), while on a Classic it is around 4.2 msecs (accuracy is ±2.1 msecs). On Macs with on-board video in DRAM (e.g. IIsi and IIci without video cards), rather than VRAM, the accuracy can be slightly worse if the program is loaded in the same memory bank as the screen buffer than when it is loaded into a different memory bank. But no matter how fast the computer is, the ADB cannot process requests faster than every 2 msecs or so. That means that if you see a program with a claim for 1 msec accuracy on all Macs, well, it might be too good to be true: with the ADB's 2 msec resolution, a reaction time program can at most claim ±1 msec accuracy (which is not the same as 1 msec accuracy: that would be ±0.5 msec). This holds unless, of course, you also get additional hardware, in which case the program does not necessarily use the ADB for responses.

To achieve its higher polling rate KeMo gives up some things, most notably the mouse cursor. When timing keyboard presses (or releases) the mouse is completely turned off, which gives a steady polling rate. When timing mouse button presses, however, the mouse still generates data when it is moved around. This data, depending on how much the mouse is being moved, can decrease the resolution of button detection to over 6 msecs. Unfortunately, even at this slower rate, there is no time to redraw the mouse cursor on the screen, so it stays frozen. For this reason the cursor is always hidden while timing of ADB events is in process (KeMoSelect() hides the cursor and KeMoReset() shows it). Important: to get mouse button polling rates that are the same as the keyboard polling rates, do not move the mouse. In an experimental situation where you want to use the mouse button, you might want to take the ball out of the mouse so it cannot be moved. Again, mouse movements do not affect the keyboard polling rate. If you need to use the cursor while checking for mouse button presses, you cannot use KeMoWait(): you need to use the Toolbox function Button(), but then you lose the accuracy KeMo gives you.

The Mac has become a complicated computer: it is often hooked up to networks and has many system extensions and INITs all running at the same time, not to mention other programs. Common sense dictates that in order to get the best results when using fast and exact display rates as well as accurate reaction time measurements a program should run with as few other programs as possible. If you have System 7, for example, hold the shift key down during the boot-up process to avoid loading any system extensions, and kill all other applications, like the Finder, at the beginning of your program (use the KeMoQuitAllApps function). With System 6, take as many things out of the System file and System folder as you can. This might be a major inconvenience so it might not be a bad idea to have a Mac that is dedicated to running reaction time experiments that require precision in measurement.

Still, even on a Mac that has no other programs running, floppy disk access, SCSI activity (e.g. hard disk access), and network activity during ADB polling introduces some loss of accuracy. These activities only affect accuracy if they occur right when the timer is started or stopped, or when the subject makes a response. Therefore try to avoid writing programs that might allow some of these interfering events to happen at sensitive times. Sometimes disk access can happen even when you don't ask for it (e.g. if you have Virtual Memory); in those cases try to find some other remedy (e.g. turn Virtual Memory off). If your Mac is hooked up to a network, run experiments with the network disconnected. Usually these inaccuracies will be 1 msec or less, but that really depends on the type of extraneous event. For the best advice in your specific situation, ask your local Mac guru what you might have to watch out for.

At the other end of the accuracy spectrum, check out

Ulrich, R. & Giray, M. (1989). Time resolution of clocks: Effects on reaction time measurement -- Good news for bad clocks. British Journal of Mathematical and Statistical Psychology, 42, 1-12.

Their main result, as I have seen it reported (I have not seen the paper myself), is that the increased variance due to timing inaccuracies is m*m/12, where m is the resolution of your timer. A clock with 16 msec resolution, then, will increase your standard deviation by

sqrt(16*16/12) = 4.6 msecs

Please check the paper for yourself, rather than taking my word for it.

Finally, to easily check the accuracy of measurements on your Mac in various environments, run the enclosed KeMoTest program and select the Accuracy option.


Click here to get the complete KeMo 1.5 Reference document and C sources.


Date: 12/19/97
From: Hisham Abboud
To: MacPsych

Hi there,

Here's my 2 cents worth on the issues of timing. Our software, SuperLab Pro, has dealt with many of these issues.

First, timing of RTs depends on two things: the resolution of the timer itself, and the resolution of the "input device". The RTs' resolution will generally be the lesser of the two.

Yes, on the Mac it is possible to obtain 1 millisecond resolution from the *timer*. Starting with System 7, you can even go further with a 20 microsecond resolution as well.

This leaves the issue of the resolution of the input device. SuperLab Pro supports a range of input methods. For the keyboard, we support it with 2 different methods. We call the first one "Generic Keyboard". This is the infamous GetNextEvent method with its 16 msec resolution. We call the second method "ADB Keyboard". This uses the ADB Manager described in Inside Macintosh manuals. We have managed to obtain a 4 msec resolution with this method even on a Mac IIci, and slightly better (about 3.4 msec) on a Power Mac 7100/66. The only time that it hasn't worked has been on PowerBooks, although some users reported that it now works on late model PowerBooks.

By the way, in our experience, all the information above applies regardless of whether it's a Power Mac or a 68K Mac.

> On 68k Macs, it is possible to by-pass the event manager and get polling information
> from the chip which controls the ADB, but this only buys another 5ms or so of resolution.

It's not a good idea to poll the ADB chip directly. It's not called for since Apple provides the necessary software (ADB Manager) to access that information.

> the ADB input limits you to a 250 Hz polling cycle. The EventManager limits you to 60 Hz.

According to Apple's hardware design guide, an ADB device should be able to respond in 250 microseconds. However, due to OS layers, we haven't been able to get much better results that the 4 msecs mentioned above.

One final note: I know of one party that claims to have obtained one millisecond resolution from the ADB keyboard. This was done by disabling interrupts and other non-essential OS functions. This is an approach that would work for someone developing custom software for in-house use, but we felt that it is not appropriate for a commercial product designed to run on a wide variety of Macs and versions of the OS.

I hope this information is useful. I wish everyone a happy holiday season!

Hisham

Hisham Abboud
Cedrus Corporation


Please send corrections and additions to Denis Pelli.